From 3eb4d547a8ee61db6c357c49a3e225ab713e3f7a Mon Sep 17 00:00:00 2001 From: Conner Turnbull <133619638+cturnbull-bitwarden@users.noreply.github.com> Date: Fri, 3 Nov 2023 18:26:47 -0400 Subject: [PATCH] [AC-1708] Teams Starter Plan (#3386) * Upgraded old 2019 plans to have the same features as 2020 and beyond * Removed redundant test and moved additional test cases to GetByOrgIdAsync_SmNoneFreePlans_ReturnsNull * Fixed issue where feature flag wasn't returning correct plans * Added teams 2010 plan * Reverted accidental change to StripePaymentService * Split feature flag logic and added some explanatory comments * Removed families changes * Resolved issue where Teams Starter could not sign up for a new org with SM enabled * Fixed issue with signing up for SM with Teams Starter * Resolved issue where an active plan could increase their SM seat count to be greater than the base seats in the password manager plan * Updated unit test to ensure Seats are higher than SmSeats * Resolved issue where getting plans would return a value that LINQ previously cached when feature flag was in a different state --- .../Queries/Projects/MaxProjectsQueryTests.cs | 1 + .../Views/Shared/_OrganizationForm.cshtml | 2 +- .../Shared/_OrganizationFormScripts.cshtml | 1 + src/Api/Controllers/PlansController.cs | 9 ++- .../Controllers/FreshsalesController.cs | 1 + src/Core/Constants.cs | 1 + src/Core/Enums/PlanType.cs | 2 + src/Core/Enums/ProductType.cs | 2 + .../StaticStore/Plans/TeamsStarterPlan.cs | 70 +++++++++++++++++++ ...UpdateSecretsManagerSubscriptionCommand.cs | 6 ++ .../Implementations/OrganizationService.cs | 5 +- src/Core/Utilities/StaticStore.cs | 5 +- .../SecretsManagerSubscriptionUpdateTests.cs | 1 + ...dSecretsManagerSubscriptionCommandTests.cs | 9 +++ ...eSecretsManagerSubscriptionCommandTests.cs | 47 +++++++++++++ .../UpgradeOrganizationPlanCommandTests.cs | 3 + .../Services/OrganizationServiceTests.cs | 11 +++ test/Core.Test/Utilities/StaticStoreTests.cs | 3 +- 18 files changed, 171 insertions(+), 8 deletions(-) create mode 100644 src/Core/Models/StaticStore/Plans/TeamsStarterPlan.cs diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/Projects/MaxProjectsQueryTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/Projects/MaxProjectsQueryTests.cs index 58c944e8e..030e31d24 100644 --- a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/Projects/MaxProjectsQueryTests.cs +++ b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/Projects/MaxProjectsQueryTests.cs @@ -55,6 +55,7 @@ public class MaxProjectsQueryTests [BitAutoData(PlanType.TeamsAnnually2019)] [BitAutoData(PlanType.TeamsAnnually2020)] [BitAutoData(PlanType.TeamsAnnually)] + [BitAutoData(PlanType.TeamsStarter)] [BitAutoData(PlanType.EnterpriseMonthly2019)] [BitAutoData(PlanType.EnterpriseMonthly2020)] [BitAutoData(PlanType.EnterpriseMonthly)] diff --git a/src/Admin/Views/Shared/_OrganizationForm.cshtml b/src/Admin/Views/Shared/_OrganizationForm.cshtml index 9e1b488b1..76502ff75 100644 --- a/src/Admin/Views/Shared/_OrganizationForm.cshtml +++ b/src/Admin/Views/Shared/_OrganizationForm.cshtml @@ -82,7 +82,7 @@ @{ var planTypes = Enum.GetValues() - .Where(p => Model.Provider == null || p is >= PlanType.TeamsMonthly and <= PlanType.EnterpriseAnnually) + .Where(p => Model.Provider == null || p is >= PlanType.TeamsMonthly and <= PlanType.TeamsStarter) .Select(e => new SelectListItem { Value = ((int)e).ToString(), diff --git a/src/Admin/Views/Shared/_OrganizationFormScripts.cshtml b/src/Admin/Views/Shared/_OrganizationFormScripts.cshtml index 5871977fe..fc527750a 100644 --- a/src/Admin/Views/Shared/_OrganizationFormScripts.cshtml +++ b/src/Admin/Views/Shared/_OrganizationFormScripts.cshtml @@ -74,6 +74,7 @@ case '@((byte)PlanType.TeamsAnnually2020)': case '@((byte)PlanType.TeamsMonthly)': case '@((byte)PlanType.TeamsAnnually)': + case '@((byte)PlanType.TeamsStarter)': document.getElementById('@(nameof(Model.UsePolicies))').checked = false; document.getElementById('@(nameof(Model.UseSso))').checked = false; document.getElementById('@(nameof(Model.UseGroups))').checked = true; diff --git a/src/Api/Controllers/PlansController.cs b/src/Api/Controllers/PlansController.cs index 14992bd97..09aa0ba1e 100644 --- a/src/Api/Controllers/PlansController.cs +++ b/src/Api/Controllers/PlansController.cs @@ -33,9 +33,12 @@ public class PlansController : Controller public ListResponseModel Get() { var plansUpgradeIsEnabled = _featureService.IsEnabled(FeatureFlagKeys.BillingPlansUpgrade, _currentContext); - var data = StaticStore.Plans; - var responses = data - .Where(plan => plansUpgradeIsEnabled || plan.Type <= PlanType.EnterpriseAnnually2020) + var teamsStarterPlanIsEnabled = _featureService.IsEnabled(FeatureFlagKeys.BillingStarterPlan, _currentContext); + var responses = StaticStore.Plans + // If plans upgrade is disabled, return only the original plans. Otherwise, return everything + .Where(plan => plansUpgradeIsEnabled || plan.Type <= PlanType.EnterpriseAnnually2020 || plan.Type == PlanType.TeamsStarter) + // If teams starter is disabled, don't return that plan, otherwise return everything + .Where(plan => teamsStarterPlanIsEnabled || plan.Product != ProductType.TeamsStarter) .Select(plan => { if (!plansUpgradeIsEnabled && plan.Type is <= PlanType.EnterpriseAnnually2020 and >= PlanType.TeamsMonthly2020) diff --git a/src/Billing/Controllers/FreshsalesController.cs b/src/Billing/Controllers/FreshsalesController.cs index a66edd6ca..545f285e0 100644 --- a/src/Billing/Controllers/FreshsalesController.cs +++ b/src/Billing/Controllers/FreshsalesController.cs @@ -164,6 +164,7 @@ public class FreshsalesController : Controller case PlanType.TeamsMonthly: case PlanType.TeamsMonthly2020: case PlanType.TeamsMonthly2019: + case PlanType.TeamsStarter: planName = "Teams"; return true; case PlanType.EnterpriseAnnually: diff --git a/src/Core/Constants.cs b/src/Core/Constants.cs index e32b0f4ce..6dbe8541d 100644 --- a/src/Core/Constants.cs +++ b/src/Core/Constants.cs @@ -64,6 +64,7 @@ public static class FeatureFlagKeys public const string AutofillOverlay = "autofill-overlay"; public const string ItemShare = "item-share"; public const string BillingPlansUpgrade = "billing-plans-upgrade"; + public const string BillingStarterPlan = "billing-starter-plan"; public static List GetAllKeys() { diff --git a/src/Core/Enums/PlanType.cs b/src/Core/Enums/PlanType.cs index cb88e8360..57fcd3090 100644 --- a/src/Core/Enums/PlanType.cs +++ b/src/Core/Enums/PlanType.cs @@ -36,4 +36,6 @@ public enum PlanType : byte EnterpriseMonthly = 14, [Display(Name = "Enterprise (Annually)")] EnterpriseAnnually = 15, + [Display(Name = "Teams Starter")] + TeamsStarter = 16, } diff --git a/src/Core/Enums/ProductType.cs b/src/Core/Enums/ProductType.cs index 1e443f56f..9d6e0e2bb 100644 --- a/src/Core/Enums/ProductType.cs +++ b/src/Core/Enums/ProductType.cs @@ -12,5 +12,7 @@ public enum ProductType : byte Teams = 2, [Display(Name = "Enterprise")] Enterprise = 3, + [Display(Name = "Teams Starter")] + TeamsStarter = 4, } diff --git a/src/Core/Models/StaticStore/Plans/TeamsStarterPlan.cs b/src/Core/Models/StaticStore/Plans/TeamsStarterPlan.cs new file mode 100644 index 000000000..1b9b1b876 --- /dev/null +++ b/src/Core/Models/StaticStore/Plans/TeamsStarterPlan.cs @@ -0,0 +1,70 @@ +using Bit.Core.Enums; + +namespace Bit.Core.Models.StaticStore.Plans; + +public record TeamsStarterPlan : Plan +{ + public TeamsStarterPlan() + { + Type = PlanType.TeamsStarter; + Product = ProductType.TeamsStarter; + Name = "Teams (Starter)"; + NameLocalizationKey = "planNameTeamsStarter"; + DescriptionLocalizationKey = "planDescTeams"; + CanBeUsedByBusiness = true; + + TrialPeriodDays = 7; + + HasGroups = true; + HasDirectory = true; + HasEvents = true; + HasTotp = true; + Has2fa = true; + HasApi = true; + UsersGetPremium = true; + + UpgradeSortOrder = 2; + DisplaySortOrder = 2; + + PasswordManager = new TeamsStarterPasswordManagerFeatures(); + SecretsManager = new TeamsStarterSecretsManagerFeatures(); + } + + private record TeamsStarterSecretsManagerFeatures : SecretsManagerPlanFeatures + { + public TeamsStarterSecretsManagerFeatures() + { + BaseSeats = 0; + BasePrice = 0; + BaseServiceAccount = 50; + + HasAdditionalSeatsOption = true; + HasAdditionalServiceAccountOption = true; + + AllowSeatAutoscale = true; + AllowServiceAccountsAutoscale = true; + + StripeSeatPlanId = "secrets-manager-teams-seat-monthly"; + StripeServiceAccountPlanId = "secrets-manager-service-account-monthly"; + SeatPrice = 7; + AdditionalPricePerServiceAccount = 0.5M; + } + } + + private record TeamsStarterPasswordManagerFeatures : PasswordManagerPlanFeatures + { + public TeamsStarterPasswordManagerFeatures() + { + BaseSeats = 10; + BaseStorageGb = 1; + BasePrice = 20; + + MaxSeats = 10; + + HasAdditionalStorageOption = true; + + StripePlanId = "teams-org-starter"; + AdditionalStoragePricePerGb = 0.5M; + } + } +} diff --git a/src/Core/OrganizationFeatures/OrganizationSubscriptions/UpdateSecretsManagerSubscriptionCommand.cs b/src/Core/OrganizationFeatures/OrganizationSubscriptions/UpdateSecretsManagerSubscriptionCommand.cs index 30ccbe578..ddfdee3f6 100644 --- a/src/Core/OrganizationFeatures/OrganizationSubscriptions/UpdateSecretsManagerSubscriptionCommand.cs +++ b/src/Core/OrganizationFeatures/OrganizationSubscriptions/UpdateSecretsManagerSubscriptionCommand.cs @@ -243,6 +243,12 @@ public class UpdateSecretsManagerSubscriptionCommand : IUpdateSecretsManagerSubs "You cannot decrease your subscription below your current occupied seat count."); } } + + // Check that SM seats aren't greater than password manager seats + if (organization.Seats < update.SmSeats.Value) + { + throw new BadRequestException("You cannot have more Secrets Manager seats than Password Manager seats."); + } } private async Task ValidateSmServiceAccountsUpdateAsync(SecretsManagerSubscriptionUpdate update) diff --git a/src/Core/Services/Implementations/OrganizationService.cs b/src/Core/Services/Implementations/OrganizationService.cs index cc504ae02..e7275a6d2 100644 --- a/src/Core/Services/Implementations/OrganizationService.cs +++ b/src/Core/Services/Implementations/OrganizationService.cs @@ -1893,7 +1893,10 @@ public class OrganizationService : IOrganizationService throw new BadRequestException("Plan does not allow additional Service Accounts."); } - if (upgrade.AdditionalSmSeats.GetValueOrDefault() > upgrade.AdditionalSeats) + if ((plan.Product == ProductType.TeamsStarter && + upgrade.AdditionalSmSeats.GetValueOrDefault() > plan.PasswordManager.BaseSeats) || + (plan.Product != ProductType.TeamsStarter && + upgrade.AdditionalSmSeats.GetValueOrDefault() > upgrade.AdditionalSeats)) { throw new BadRequestException("You cannot have more Secrets Manager seats than Password Manager seats."); } diff --git a/src/Core/Utilities/StaticStore.cs b/src/Core/Utilities/StaticStore.cs index 11052a446..dcf63df13 100644 --- a/src/Core/Utilities/StaticStore.cs +++ b/src/Core/Utilities/StaticStore.cs @@ -106,10 +106,11 @@ public static class StaticStore GlobalDomains.Add(GlobalEquivalentDomainsType.Pinterest, new List { "pinterest.com", "pinterest.com.au", "pinterest.cl", "pinterest.de", "pinterest.dk", "pinterest.es", "pinterest.fr", "pinterest.co.uk", "pinterest.jp", "pinterest.co.kr", "pinterest.nz", "pinterest.pt", "pinterest.se" }); #endregion - Plans = new List + Plans = new List { new EnterprisePlan(true), new EnterprisePlan(false), + new TeamsStarterPlan(), new TeamsPlan(true), new TeamsPlan(false), @@ -130,7 +131,7 @@ public static class StaticStore } public static IDictionary> GlobalDomains { get; set; } - public static IEnumerable Plans { get; } + public static IEnumerable Plans { get; } public static IEnumerable SponsoredPlans { get; set; } = new[] { new SponsoredPlan diff --git a/test/Core.Test/Models/Business/SecretsManagerSubscriptionUpdateTests.cs b/test/Core.Test/Models/Business/SecretsManagerSubscriptionUpdateTests.cs index 88e21862b..ce08065ab 100644 --- a/test/Core.Test/Models/Business/SecretsManagerSubscriptionUpdateTests.cs +++ b/test/Core.Test/Models/Business/SecretsManagerSubscriptionUpdateTests.cs @@ -43,6 +43,7 @@ public class SecretsManagerSubscriptionUpdateTests [BitAutoData(PlanType.TeamsAnnually2019)] [BitAutoData(PlanType.TeamsAnnually2020)] [BitAutoData(PlanType.TeamsAnnually)] + [BitAutoData(PlanType.TeamsStarter)] public void UpdateSubscription_WithNonSecretsManagerPlanType_DoesNotThrowException( PlanType planType, Organization organization) diff --git a/test/Core.Test/OrganizationFeatures/OrganizationSubscriptionUpdate/AddSecretsManagerSubscriptionCommandTests.cs b/test/Core.Test/OrganizationFeatures/OrganizationSubscriptionUpdate/AddSecretsManagerSubscriptionCommandTests.cs index e3b948719..46987d6fc 100644 --- a/test/Core.Test/OrganizationFeatures/OrganizationSubscriptionUpdate/AddSecretsManagerSubscriptionCommandTests.cs +++ b/test/Core.Test/OrganizationFeatures/OrganizationSubscriptionUpdate/AddSecretsManagerSubscriptionCommandTests.cs @@ -19,9 +19,18 @@ namespace Bit.Core.Test.OrganizationFeatures.OrganizationSubscriptionUpdate; public class AddSecretsManagerSubscriptionCommandTests { [Theory] + [BitAutoData(PlanType.TeamsAnnually2019)] + [BitAutoData(PlanType.TeamsAnnually2020)] [BitAutoData(PlanType.TeamsAnnually)] + [BitAutoData(PlanType.TeamsMonthly2019)] + [BitAutoData(PlanType.TeamsMonthly2020)] [BitAutoData(PlanType.TeamsMonthly)] + [BitAutoData(PlanType.TeamsStarter)] + [BitAutoData(PlanType.EnterpriseAnnually2019)] + [BitAutoData(PlanType.EnterpriseAnnually2020)] [BitAutoData(PlanType.EnterpriseAnnually)] + [BitAutoData(PlanType.EnterpriseMonthly2019)] + [BitAutoData(PlanType.EnterpriseMonthly2020)] [BitAutoData(PlanType.EnterpriseMonthly)] public async Task SignUpAsync_ReturnsSuccessAndClientSecret_WhenOrganizationAndPlanExist(PlanType planType, SutProvider sutProvider, diff --git a/test/Core.Test/OrganizationFeatures/OrganizationSubscriptionUpdate/UpdateSecretsManagerSubscriptionCommandTests.cs b/test/Core.Test/OrganizationFeatures/OrganizationSubscriptionUpdate/UpdateSecretsManagerSubscriptionCommandTests.cs index 16508bd25..c17ab2b83 100644 --- a/test/Core.Test/OrganizationFeatures/OrganizationSubscriptionUpdate/UpdateSecretsManagerSubscriptionCommandTests.cs +++ b/test/Core.Test/OrganizationFeatures/OrganizationSubscriptionUpdate/UpdateSecretsManagerSubscriptionCommandTests.cs @@ -22,16 +22,26 @@ namespace Bit.Core.Test.OrganizationFeatures.OrganizationSubscriptionUpdate; public class UpdateSecretsManagerSubscriptionCommandTests { [Theory] + [BitAutoData(PlanType.EnterpriseAnnually2019)] + [BitAutoData(PlanType.EnterpriseAnnually2020)] [BitAutoData(PlanType.EnterpriseAnnually)] + [BitAutoData(PlanType.EnterpriseMonthly2019)] + [BitAutoData(PlanType.EnterpriseMonthly2020)] [BitAutoData(PlanType.EnterpriseMonthly)] + [BitAutoData(PlanType.TeamsMonthly2019)] + [BitAutoData(PlanType.TeamsMonthly2020)] [BitAutoData(PlanType.TeamsMonthly)] + [BitAutoData(PlanType.TeamsAnnually2019)] + [BitAutoData(PlanType.TeamsAnnually2020)] [BitAutoData(PlanType.TeamsAnnually)] + [BitAutoData(PlanType.TeamsStarter)] public async Task UpdateSubscriptionAsync_UpdateEverything_ValidInput_Passes( PlanType planType, Organization organization, SutProvider sutProvider) { organization.PlanType = planType; + organization.Seats = 400; organization.SmSeats = 10; organization.MaxAutoscaleSmSeats = 20; organization.SmServiceAccounts = 200; @@ -77,6 +87,7 @@ public class UpdateSecretsManagerSubscriptionCommandTests [BitAutoData(PlanType.EnterpriseMonthly)] [BitAutoData(PlanType.TeamsMonthly)] [BitAutoData(PlanType.TeamsAnnually)] + [BitAutoData(PlanType.TeamsStarter)] public async Task UpdateSubscriptionAsync_ValidInput_WithNullMaxAutoscale_Passes( PlanType planType, Organization organization, @@ -168,10 +179,19 @@ public class UpdateSecretsManagerSubscriptionCommandTests } [Theory] + [BitAutoData(PlanType.EnterpriseAnnually2019)] + [BitAutoData(PlanType.EnterpriseAnnually2020)] [BitAutoData(PlanType.EnterpriseAnnually)] + [BitAutoData(PlanType.EnterpriseMonthly2019)] + [BitAutoData(PlanType.EnterpriseMonthly2020)] [BitAutoData(PlanType.EnterpriseMonthly)] + [BitAutoData(PlanType.TeamsMonthly2019)] + [BitAutoData(PlanType.TeamsMonthly2020)] [BitAutoData(PlanType.TeamsMonthly)] + [BitAutoData(PlanType.TeamsAnnually2019)] + [BitAutoData(PlanType.TeamsAnnually2020)] [BitAutoData(PlanType.TeamsAnnually)] + [BitAutoData(PlanType.TeamsStarter)] public async Task UpdateSubscriptionAsync_PaidPlan_NullGatewayCustomerId_ThrowsException( PlanType planType, Organization organization, @@ -187,10 +207,19 @@ public class UpdateSecretsManagerSubscriptionCommandTests } [Theory] + [BitAutoData(PlanType.EnterpriseAnnually2019)] + [BitAutoData(PlanType.EnterpriseAnnually2020)] [BitAutoData(PlanType.EnterpriseAnnually)] + [BitAutoData(PlanType.EnterpriseMonthly2019)] + [BitAutoData(PlanType.EnterpriseMonthly2020)] [BitAutoData(PlanType.EnterpriseMonthly)] + [BitAutoData(PlanType.TeamsMonthly2019)] + [BitAutoData(PlanType.TeamsMonthly2020)] [BitAutoData(PlanType.TeamsMonthly)] + [BitAutoData(PlanType.TeamsAnnually2019)] + [BitAutoData(PlanType.TeamsAnnually2020)] [BitAutoData(PlanType.TeamsAnnually)] + [BitAutoData(PlanType.TeamsStarter)] public async Task UpdateSubscriptionAsync_PaidPlan_NullGatewaySubscriptionId_ThrowsException( PlanType planType, Organization organization, @@ -206,10 +235,19 @@ public class UpdateSecretsManagerSubscriptionCommandTests } [Theory] + [BitAutoData(PlanType.EnterpriseAnnually2019)] + [BitAutoData(PlanType.EnterpriseAnnually2020)] [BitAutoData(PlanType.EnterpriseAnnually)] + [BitAutoData(PlanType.EnterpriseMonthly2019)] + [BitAutoData(PlanType.EnterpriseMonthly2020)] [BitAutoData(PlanType.EnterpriseMonthly)] + [BitAutoData(PlanType.TeamsMonthly2019)] + [BitAutoData(PlanType.TeamsMonthly2020)] [BitAutoData(PlanType.TeamsMonthly)] + [BitAutoData(PlanType.TeamsAnnually2019)] + [BitAutoData(PlanType.TeamsAnnually2020)] [BitAutoData(PlanType.TeamsAnnually)] + [BitAutoData(PlanType.TeamsStarter)] public async Task AdjustServiceAccountsAsync_WithEnterpriseOrTeamsPlans_Success(PlanType planType, Guid organizationId, SutProvider sutProvider) { @@ -501,10 +539,19 @@ public class UpdateSecretsManagerSubscriptionCommandTests } [Theory] + [BitAutoData(PlanType.EnterpriseAnnually2019)] + [BitAutoData(PlanType.EnterpriseAnnually2020)] [BitAutoData(PlanType.EnterpriseAnnually)] + [BitAutoData(PlanType.EnterpriseMonthly2019)] + [BitAutoData(PlanType.EnterpriseMonthly2020)] [BitAutoData(PlanType.EnterpriseMonthly)] + [BitAutoData(PlanType.TeamsMonthly2019)] + [BitAutoData(PlanType.TeamsMonthly2020)] [BitAutoData(PlanType.TeamsMonthly)] + [BitAutoData(PlanType.TeamsAnnually2019)] + [BitAutoData(PlanType.TeamsAnnually2020)] [BitAutoData(PlanType.TeamsAnnually)] + [BitAutoData(PlanType.TeamsStarter)] public async Task UpdateSmServiceAccounts_WhenCurrentServiceAccountsIsGreaterThanNew_ThrowsBadRequestException( PlanType planType, Organization organization, diff --git a/test/Core.Test/OrganizationFeatures/OrganizationSubscriptionUpdate/UpgradeOrganizationPlanCommandTests.cs b/test/Core.Test/OrganizationFeatures/OrganizationSubscriptionUpdate/UpgradeOrganizationPlanCommandTests.cs index f79001639..b7f7d32cb 100644 --- a/test/Core.Test/OrganizationFeatures/OrganizationSubscriptionUpdate/UpgradeOrganizationPlanCommandTests.cs +++ b/test/Core.Test/OrganizationFeatures/OrganizationSubscriptionUpdate/UpgradeOrganizationPlanCommandTests.cs @@ -104,6 +104,7 @@ public class UpgradeOrganizationPlanCommandTests [BitAutoData(PlanType.EnterpriseAnnually)] [BitAutoData(PlanType.TeamsMonthly)] [BitAutoData(PlanType.TeamsAnnually)] + [BitAutoData(PlanType.TeamsStarter)] public async Task UpgradePlan_SM_Passes(PlanType planType, Organization organization, OrganizationUpgrade upgrade, SutProvider sutProvider) { @@ -135,6 +136,7 @@ public class UpgradeOrganizationPlanCommandTests [BitAutoData(PlanType.EnterpriseAnnually)] [BitAutoData(PlanType.TeamsMonthly)] [BitAutoData(PlanType.TeamsAnnually)] + [BitAutoData(PlanType.TeamsStarter)] public async Task UpgradePlan_SM_NotEnoughSmSeats_Throws(PlanType planType, Organization organization, OrganizationUpgrade upgrade, SutProvider sutProvider) { @@ -160,6 +162,7 @@ public class UpgradeOrganizationPlanCommandTests [BitAutoData(PlanType.EnterpriseAnnually, 201)] [BitAutoData(PlanType.TeamsMonthly, 51)] [BitAutoData(PlanType.TeamsAnnually, 51)] + [BitAutoData(PlanType.TeamsStarter, 51)] public async Task UpgradePlan_SM_NotEnoughServiceAccounts_Throws(PlanType planType, int currentServiceAccounts, Organization organization, OrganizationUpgrade upgrade, SutProvider sutProvider) { diff --git a/test/Core.Test/Services/OrganizationServiceTests.cs b/test/Core.Test/Services/OrganizationServiceTests.cs index b0421309b..210e59681 100644 --- a/test/Core.Test/Services/OrganizationServiceTests.cs +++ b/test/Core.Test/Services/OrganizationServiceTests.cs @@ -1355,10 +1355,14 @@ public class OrganizationServiceTests [BitAutoData(PlanType.Custom, OrganizationUserType.Owner)] [BitAutoData(PlanType.EnterpriseAnnually, OrganizationUserType.Admin)] [BitAutoData(PlanType.EnterpriseAnnually, OrganizationUserType.Owner)] + [BitAutoData(PlanType.EnterpriseAnnually2020, OrganizationUserType.Admin)] + [BitAutoData(PlanType.EnterpriseAnnually2020, OrganizationUserType.Owner)] [BitAutoData(PlanType.EnterpriseAnnually2019, OrganizationUserType.Admin)] [BitAutoData(PlanType.EnterpriseAnnually2019, OrganizationUserType.Owner)] [BitAutoData(PlanType.EnterpriseMonthly, OrganizationUserType.Admin)] [BitAutoData(PlanType.EnterpriseMonthly, OrganizationUserType.Owner)] + [BitAutoData(PlanType.EnterpriseMonthly2020, OrganizationUserType.Admin)] + [BitAutoData(PlanType.EnterpriseMonthly2020, OrganizationUserType.Owner)] [BitAutoData(PlanType.EnterpriseMonthly2019, OrganizationUserType.Admin)] [BitAutoData(PlanType.EnterpriseMonthly2019, OrganizationUserType.Owner)] [BitAutoData(PlanType.FamiliesAnnually, OrganizationUserType.Admin)] @@ -1367,10 +1371,14 @@ public class OrganizationServiceTests [BitAutoData(PlanType.FamiliesAnnually2019, OrganizationUserType.Owner)] [BitAutoData(PlanType.TeamsAnnually, OrganizationUserType.Admin)] [BitAutoData(PlanType.TeamsAnnually, OrganizationUserType.Owner)] + [BitAutoData(PlanType.TeamsAnnually2020, OrganizationUserType.Admin)] + [BitAutoData(PlanType.TeamsAnnually2020, OrganizationUserType.Owner)] [BitAutoData(PlanType.TeamsAnnually2019, OrganizationUserType.Admin)] [BitAutoData(PlanType.TeamsAnnually2019, OrganizationUserType.Owner)] [BitAutoData(PlanType.TeamsMonthly, OrganizationUserType.Admin)] [BitAutoData(PlanType.TeamsMonthly, OrganizationUserType.Owner)] + [BitAutoData(PlanType.TeamsMonthly2020, OrganizationUserType.Admin)] + [BitAutoData(PlanType.TeamsMonthly2020, OrganizationUserType.Owner)] [BitAutoData(PlanType.TeamsMonthly2019, OrganizationUserType.Admin)] [BitAutoData(PlanType.TeamsMonthly2019, OrganizationUserType.Owner)] public async Task ConfirmUserToNonFree_AlreadyFreeAdminOrOwner_DoesNotThrow(PlanType planType, OrganizationUserType orgUserType, Organization org, OrganizationUser confirmingUser, @@ -1791,6 +1799,7 @@ public class OrganizationServiceTests [Theory] [BitAutoData(PlanType.TeamsAnnually)] [BitAutoData(PlanType.TeamsMonthly)] + [BitAutoData(PlanType.TeamsStarter)] [BitAutoData(PlanType.EnterpriseAnnually)] [BitAutoData(PlanType.EnterpriseMonthly)] public void ValidateSecretsManagerPlan_ThrowsException_WhenNoSecretsManagerSeats(PlanType planType, SutProvider sutProvider) @@ -1863,6 +1872,7 @@ public class OrganizationServiceTests [Theory] [BitAutoData(PlanType.TeamsAnnually)] [BitAutoData(PlanType.TeamsMonthly)] + [BitAutoData(PlanType.TeamsStarter)] [BitAutoData(PlanType.EnterpriseAnnually)] [BitAutoData(PlanType.EnterpriseMonthly)] public void ValidateSecretsManagerPlan_ThrowsException_WhenSubtractingServiceAccounts( @@ -1902,6 +1912,7 @@ public class OrganizationServiceTests [Theory] [BitAutoData(PlanType.TeamsAnnually)] [BitAutoData(PlanType.TeamsMonthly)] + [BitAutoData(PlanType.TeamsStarter)] [BitAutoData(PlanType.EnterpriseAnnually)] [BitAutoData(PlanType.EnterpriseMonthly)] public void ValidateSecretsManagerPlan_ValidPlan_NoExceptionThrown( diff --git a/test/Core.Test/Utilities/StaticStoreTests.cs b/test/Core.Test/Utilities/StaticStoreTests.cs index 9abd31c8f..4b16ec96f 100644 --- a/test/Core.Test/Utilities/StaticStoreTests.cs +++ b/test/Core.Test/Utilities/StaticStoreTests.cs @@ -13,7 +13,7 @@ public class StaticStoreTests var plans = StaticStore.Plans.ToList(); Assert.NotNull(plans); Assert.NotEmpty(plans); - Assert.Equal(16, plans.Count); + Assert.Equal(17, plans.Count); } [Theory] @@ -21,6 +21,7 @@ public class StaticStoreTests [InlineData(PlanType.EnterpriseMonthly)] [InlineData(PlanType.TeamsMonthly)] [InlineData(PlanType.TeamsAnnually)] + [InlineData(PlanType.TeamsStarter)] public void StaticStore_GetPlan_Success(PlanType planType) { var plan = StaticStore.GetPlan(planType);