mirror of
https://github.com/bitwarden/server.git
synced 2026-06-01 12:26:46 -05:00
* test(billing): Add unit tests for TrialInitiationCache * feat(billing): Add trial initiation cache interface and implementation * feat(billing): Register trial initiation cache services * feat(core): Add trial properties to OrganizationSignup model * feat(mail): Update trial verification email model and services for TrialInitiationId * feat(billing): Enhance TrialSendVerificationEmailRequestModel validation * test(billing): Add tests for TrialSendVerificationEmailRequestModel validation * feat(billing): Introduce default trial length constant * refactor(identity): Use constant for default trial length in AccountsController * test(identity): Update accounts controller tests for default trial length constant * feat(billing): Integrate trial initiation into email sending command * feat(billing): Add TrialLength to SubscriptionSetup model * feat(billing): Map TrialLength in OrganizationSale creation * feat(billing): Allow custom trial length in organization billing service * feat(admin-console): Add TrialLength and TrialInitiationId to organization creation requests * feat(admin-console): Validate trial length during cloud organization signup * test(admin-console): Add tests for organization create request trial properties * test(admin-console): Add tests for CloudOrganizationSignUpCommand trial length validation * refactor(TrialInitiationCache): change validation method to retrieval * test(TrialInitiationCache): update tests for GetAndRemoveAsync * feat(OrganizationSignUp): refactor trial validation to command * test(OrganizationSignUp): add trial validation scenarios * test(OrganizationSignUp): nullify TrialLength in unrelated tests * fix(billing): dotnet format * refactor: remove `TrialInitiationId` property from data models refactor: update mail service interfaces and implementations * refactor: remove `ITrialInitiationCache` infrastructure test: update `CloudOrganizationSignUpCommandTests` for trial validation * refactor: update `SendTrialInitiationEmailForRegistrationCommand` * refactor: update `CloudOrganizationSignUpCommand` trial length validation * test(organization): fix plan call in tests * test(billing): fix test settings
242 lines
8.4 KiB
C#
242 lines
8.4 KiB
C#
using Bit.Core.Billing.Constants;
|
|
using Bit.Core.Billing.Enums;
|
|
using Bit.Core.Billing.Models.Api.Requests.Accounts;
|
|
using Bit.Core.Billing.TrialInitiation.Registration;
|
|
using Bit.Identity.Billing.Controller;
|
|
using Bit.Test.Common.AutoFixture.Attributes;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using NSubstitute;
|
|
using Xunit;
|
|
|
|
namespace Bit.Identity.Test.Billing.Controller;
|
|
|
|
public class AccountsControllerTests
|
|
{
|
|
private readonly ISendTrialInitiationEmailForRegistrationCommand _sendTrialInitiationEmailForRegistrationCommand;
|
|
private readonly AccountsController _sut;
|
|
|
|
public AccountsControllerTests()
|
|
{
|
|
_sendTrialInitiationEmailForRegistrationCommand = Substitute.For<ISendTrialInitiationEmailForRegistrationCommand>();
|
|
_sut = new AccountsController(_sendTrialInitiationEmailForRegistrationCommand);
|
|
}
|
|
|
|
[Theory]
|
|
[BitAutoData]
|
|
public async Task PostTrialInitiationSendVerificationEmailAsync_PaymentOptionalTrue_TrialLengthZero_ReturnsBadRequest(
|
|
string email,
|
|
string name,
|
|
bool receiveMarketingEmails,
|
|
ProductTierType productTier,
|
|
IEnumerable<ProductType> products)
|
|
{
|
|
// Arrange
|
|
var model = new TrialSendVerificationEmailRequestModel
|
|
{
|
|
Email = email,
|
|
Name = name,
|
|
ReceiveMarketingEmails = receiveMarketingEmails,
|
|
ProductTier = productTier,
|
|
Products = products,
|
|
TrialLength = 0,
|
|
PaymentOptional = true
|
|
};
|
|
|
|
// Act
|
|
var result = await _sut.PostTrialInitiationSendVerificationEmailAsync(model);
|
|
|
|
// Assert
|
|
var badRequestResult = Assert.IsType<BadRequestObjectResult>(result);
|
|
Assert.Equal(400, badRequestResult.StatusCode);
|
|
|
|
var value = badRequestResult.Value;
|
|
var messageProperty = value?.GetType().GetProperty("message");
|
|
Assert.NotNull(messageProperty);
|
|
Assert.Equal("Payment cannot be optional when trial length is zero.", messageProperty.GetValue(value));
|
|
|
|
await _sendTrialInitiationEmailForRegistrationCommand.DidNotReceive()
|
|
.Handle(Arg.Any<string>(), Arg.Any<string>(), Arg.Any<bool>(), Arg.Any<ProductTierType>(),
|
|
Arg.Any<IEnumerable<ProductType>>(), Arg.Any<int>(), Arg.Any<bool>());
|
|
}
|
|
|
|
[Theory]
|
|
[BitAutoData]
|
|
public async Task PostTrialInitiationSendVerificationEmailAsync_PaymentOptionalTrue_TrialLengthNonZero_ReturnsSuccess(
|
|
string email,
|
|
string name,
|
|
bool receiveMarketingEmails,
|
|
ProductTierType productTier,
|
|
IEnumerable<ProductType> products,
|
|
string token)
|
|
{
|
|
// Arrange
|
|
var trialLength = 7;
|
|
var model = new TrialSendVerificationEmailRequestModel
|
|
{
|
|
Email = email,
|
|
Name = name,
|
|
ReceiveMarketingEmails = receiveMarketingEmails,
|
|
ProductTier = productTier,
|
|
Products = products,
|
|
TrialLength = trialLength,
|
|
PaymentOptional = true
|
|
};
|
|
|
|
_sendTrialInitiationEmailForRegistrationCommand
|
|
.Handle(email, name, receiveMarketingEmails, productTier, products, trialLength, true)
|
|
.Returns(token);
|
|
|
|
// Act
|
|
var result = await _sut.PostTrialInitiationSendVerificationEmailAsync(model);
|
|
|
|
// Assert
|
|
var okResult = Assert.IsType<OkObjectResult>(result);
|
|
Assert.Equal(200, okResult.StatusCode);
|
|
Assert.Equal(token, okResult.Value);
|
|
|
|
await _sendTrialInitiationEmailForRegistrationCommand.Received(1)
|
|
.Handle(email, name, receiveMarketingEmails, productTier, products, trialLength, true);
|
|
}
|
|
|
|
[Theory]
|
|
[BitAutoData]
|
|
public async Task PostTrialInitiationSendVerificationEmailAsync_PaymentOptionalFalse_TrialLengthZero_ReturnsSuccess(
|
|
string email,
|
|
string name,
|
|
bool receiveMarketingEmails,
|
|
ProductTierType productTier,
|
|
IEnumerable<ProductType> products)
|
|
{
|
|
// Arrange
|
|
var model = new TrialSendVerificationEmailRequestModel
|
|
{
|
|
Email = email,
|
|
Name = name,
|
|
ReceiveMarketingEmails = receiveMarketingEmails,
|
|
ProductTier = productTier,
|
|
Products = products,
|
|
TrialLength = 0,
|
|
PaymentOptional = false
|
|
};
|
|
|
|
_sendTrialInitiationEmailForRegistrationCommand
|
|
.Handle(email, name, receiveMarketingEmails, productTier, products, 0, false)
|
|
.Returns((string?)null);
|
|
|
|
// Act
|
|
var result = await _sut.PostTrialInitiationSendVerificationEmailAsync(model);
|
|
|
|
// Assert
|
|
var noContentResult = Assert.IsType<NoContentResult>(result);
|
|
Assert.Equal(204, noContentResult.StatusCode);
|
|
|
|
await _sendTrialInitiationEmailForRegistrationCommand.Received(1)
|
|
.Handle(email, name, receiveMarketingEmails, productTier, products, 0, false);
|
|
}
|
|
|
|
[Theory]
|
|
[BitAutoData]
|
|
public async Task PostTrialInitiationSendVerificationEmailAsync_TrialLengthNull_DefaultsToDefaultTrialLength(
|
|
string email,
|
|
string name,
|
|
bool receiveMarketingEmails,
|
|
ProductTierType productTier,
|
|
IEnumerable<ProductType> products,
|
|
string token)
|
|
{
|
|
// Arrange
|
|
var model = new TrialSendVerificationEmailRequestModel
|
|
{
|
|
Email = email,
|
|
Name = name,
|
|
ReceiveMarketingEmails = receiveMarketingEmails,
|
|
ProductTier = productTier,
|
|
Products = products,
|
|
TrialLength = null,
|
|
PaymentOptional = false
|
|
};
|
|
|
|
_sendTrialInitiationEmailForRegistrationCommand
|
|
.Handle(email, name, receiveMarketingEmails, productTier, products,
|
|
TrialInitiationConstants.DefaultTrialLengthDays, false)
|
|
.Returns(token);
|
|
|
|
// Act
|
|
var result = await _sut.PostTrialInitiationSendVerificationEmailAsync(model);
|
|
|
|
// Assert
|
|
var okResult = Assert.IsType<OkObjectResult>(result);
|
|
Assert.Equal(200, okResult.StatusCode);
|
|
|
|
await _sendTrialInitiationEmailForRegistrationCommand.Received(1)
|
|
.Handle(email, name, receiveMarketingEmails, productTier, products,
|
|
TrialInitiationConstants.DefaultTrialLengthDays, false);
|
|
}
|
|
|
|
[Theory]
|
|
[BitAutoData]
|
|
public async Task PostTrialInitiationSendVerificationEmailAsync_CommandReturnsNull_ReturnsNoContent(
|
|
string email,
|
|
string name,
|
|
bool receiveMarketingEmails,
|
|
ProductTierType productTier,
|
|
IEnumerable<ProductType> products)
|
|
{
|
|
// Arrange
|
|
var model = new TrialSendVerificationEmailRequestModel
|
|
{
|
|
Email = email,
|
|
Name = name,
|
|
ReceiveMarketingEmails = receiveMarketingEmails,
|
|
ProductTier = productTier,
|
|
Products = products,
|
|
TrialLength = 7,
|
|
PaymentOptional = false
|
|
};
|
|
|
|
_sendTrialInitiationEmailForRegistrationCommand
|
|
.Handle(email, name, receiveMarketingEmails, productTier, products, 7, false)
|
|
.Returns((string?)null);
|
|
|
|
// Act
|
|
var result = await _sut.PostTrialInitiationSendVerificationEmailAsync(model);
|
|
|
|
// Assert
|
|
var noContentResult = Assert.IsType<NoContentResult>(result);
|
|
Assert.Equal(204, noContentResult.StatusCode);
|
|
}
|
|
|
|
[Theory]
|
|
[BitAutoData]
|
|
public async Task PostTrialInitiationSendVerificationEmailAsync_PaymentOptionalTrue_PassedToCommand(
|
|
string email,
|
|
string name,
|
|
bool receiveMarketingEmails,
|
|
ProductTierType productTier,
|
|
IEnumerable<ProductType> products)
|
|
{
|
|
// Arrange
|
|
var model = new TrialSendVerificationEmailRequestModel
|
|
{
|
|
Email = email,
|
|
Name = name,
|
|
ReceiveMarketingEmails = receiveMarketingEmails,
|
|
ProductTier = productTier,
|
|
Products = products,
|
|
TrialLength = 14,
|
|
PaymentOptional = true
|
|
};
|
|
|
|
_sendTrialInitiationEmailForRegistrationCommand
|
|
.Handle(email, name, receiveMarketingEmails, productTier, products, 14, true)
|
|
.Returns((string?)null);
|
|
|
|
// Act
|
|
await _sut.PostTrialInitiationSendVerificationEmailAsync(model);
|
|
|
|
// Assert
|
|
await _sendTrialInitiationEmailForRegistrationCommand.Received(1)
|
|
.Handle(email, name, receiveMarketingEmails, productTier, products, 14, true);
|
|
}
|
|
}
|