mirror of
https://github.com/bitwarden/server
synced 2026-03-01 02:41:33 +00:00
[PM-32796] Fix bulk reinvite timeouts by moving updated org emails from IMailer to IMailService (#7105)
This commit is contained in:
@@ -390,7 +390,7 @@ public class AutomaticallyConfirmUsersCommandTests
|
||||
|
||||
var emailException = new Exception("Email sending failed");
|
||||
sutProvider.GetDependency<IMailService>()
|
||||
.SendOrganizationConfirmedEmailAsync(organization.Name, user.Email, organizationUser.AccessSecretsManager)
|
||||
.SendOrganizationConfirmedEmailAsync(organization.DisplayName(), user.Email, organizationUser.AccessSecretsManager)
|
||||
.ThrowsAsync(emailException);
|
||||
|
||||
// Act
|
||||
@@ -705,7 +705,7 @@ public class AutomaticallyConfirmUsersCommandTests
|
||||
await sutProvider.GetDependency<IMailService>()
|
||||
.Received(1)
|
||||
.SendOrganizationConfirmedEmailAsync(
|
||||
organization.Name,
|
||||
organization.DisplayName(),
|
||||
user.Email,
|
||||
organizationUser.AccessSecretsManager);
|
||||
|
||||
@@ -722,7 +722,7 @@ public class AutomaticallyConfirmUsersCommandTests
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task SendOrganizationConfirmedEmailAsync_WithFeatureFlagOn_UsesNewMailer(
|
||||
public async Task SendOrganizationConfirmedEmailAsync_WithFeatureFlagOn_CallsSendOrganizationConfirmationCommand(
|
||||
Organization organization,
|
||||
string userEmail,
|
||||
SutProvider<AutomaticallyConfirmOrganizationUserCommand> sutProvider)
|
||||
@@ -741,8 +741,8 @@ public class AutomaticallyConfirmUsersCommandTests
|
||||
.Received(1)
|
||||
.SendConfirmationAsync(organization, userEmail, accessSecretsManager);
|
||||
await sutProvider.GetDependency<IMailService>()
|
||||
.DidNotReceive()
|
||||
.SendOrganizationConfirmedEmailAsync(Arg.Any<string>(), Arg.Any<string>(), Arg.Any<bool>());
|
||||
.DidNotReceiveWithAnyArgs()
|
||||
.SendOrganizationConfirmedEmailAsync(default, default, default);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@@ -764,9 +764,9 @@ public class AutomaticallyConfirmUsersCommandTests
|
||||
// Assert
|
||||
await sutProvider.GetDependency<IMailService>()
|
||||
.Received(1)
|
||||
.SendOrganizationConfirmedEmailAsync(organization.Name, userEmail, accessSecretsManager);
|
||||
.SendOrganizationConfirmedEmailAsync(organization.DisplayName(), userEmail, accessSecretsManager);
|
||||
await sutProvider.GetDependency<ISendOrganizationConfirmationCommand>()
|
||||
.DidNotReceive()
|
||||
.SendConfirmationAsync(Arg.Any<Organization>(), Arg.Any<string>(), Arg.Any<bool>());
|
||||
.DidNotReceiveWithAnyArgs()
|
||||
.SendConfirmationAsync(default, default, default);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -797,7 +797,7 @@ public class ConfirmOrganizationUserCommandTests
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task SendOrganizationConfirmedEmailAsync_WithFeatureFlagOn_UsesNewMailer(
|
||||
public async Task SendOrganizationConfirmedEmailAsync_WithFeatureFlagOn_CallsSendOrganizationConfirmationCommand(
|
||||
Organization org,
|
||||
string userEmail,
|
||||
SutProvider<ConfirmOrganizationUserCommand> sutProvider)
|
||||
@@ -816,8 +816,8 @@ public class ConfirmOrganizationUserCommandTests
|
||||
.Received(1)
|
||||
.SendConfirmationAsync(org, userEmail, accessSecretsManager);
|
||||
await sutProvider.GetDependency<IMailService>()
|
||||
.DidNotReceive()
|
||||
.SendOrganizationConfirmedEmailAsync(Arg.Any<string>(), Arg.Any<string>(), Arg.Any<bool>());
|
||||
.DidNotReceiveWithAnyArgs()
|
||||
.SendOrganizationConfirmedEmailAsync(default, default, default);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
@@ -840,8 +840,8 @@ public class ConfirmOrganizationUserCommandTests
|
||||
.Received(1)
|
||||
.SendOrganizationConfirmedEmailAsync(org.DisplayName(), userEmail, accessSecretsManager);
|
||||
await sutProvider.GetDependency<ISendOrganizationConfirmationCommand>()
|
||||
.DidNotReceive()
|
||||
.SendConfirmationAsync(Arg.Any<Organization>(), Arg.Any<string>(), Arg.Any<bool>());
|
||||
.DidNotReceiveWithAnyArgs()
|
||||
.SendConfirmationAsync(default, default, default);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.AdminConsole.Enums;
|
||||
using Bit.Core.AdminConsole.Models.Data.Organizations.Policies;
|
||||
using Bit.Core.AdminConsole.Models.Mail.Mailer.OrganizationInvite;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.InviteUsers;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.InviteUsers.Models;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.Policies;
|
||||
@@ -11,7 +10,6 @@ using Bit.Core.Auth.Repositories;
|
||||
using Bit.Core.Billing.Enums;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Models.Mail;
|
||||
using Bit.Core.Platform.Mail.Mailer;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Test.AdminConsole.AutoFixture;
|
||||
@@ -23,7 +21,6 @@ using Bit.Test.Common.Fakes;
|
||||
using NSubstitute;
|
||||
using NSubstitute.ReturnsExtensions;
|
||||
using Xunit;
|
||||
using CoreGlobalSettings = Bit.Core.Settings.GlobalSettings;
|
||||
|
||||
namespace Bit.Core.Test.AdminConsole.OrganizationFeatures.OrganizationUsers.InviteUsers;
|
||||
|
||||
@@ -117,15 +114,13 @@ public class SendOrganizationInvitesCommandTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(PlanType.EnterpriseAnnually, false)]
|
||||
[BitAutoData(PlanType.EnterpriseMonthly2023, false)]
|
||||
[BitAutoData(PlanType.TeamsAnnually, false)]
|
||||
[BitAutoData(PlanType.TeamsStarter, false)]
|
||||
[BitAutoData(PlanType.EnterpriseAnnually, true)]
|
||||
[BitAutoData(PlanType.TeamsAnnually, true)]
|
||||
public async Task SendInvitesAsync_WithFeatureFlag_EnterpriseAndTeamsPlans_SendsEnterpriseTemplate(
|
||||
[BitAutoData(PlanType.EnterpriseAnnually)]
|
||||
[BitAutoData(PlanType.TeamsAnnually)]
|
||||
[BitAutoData(PlanType.FamiliesAnnually)]
|
||||
[BitAutoData(PlanType.Free)]
|
||||
[BitAutoData(PlanType.Custom)]
|
||||
public async Task SendInvitesAsync_WithFeatureFlagEnabled_CallsMailServiceWithNewTemplates(
|
||||
PlanType planType,
|
||||
bool userExists,
|
||||
Organization organization,
|
||||
OrganizationUser invite,
|
||||
User invitingUser,
|
||||
@@ -137,107 +132,6 @@ public class SendOrganizationInvitesCommandTests
|
||||
organization.PlanType = planType;
|
||||
invite.OrganizationId = organization.Id;
|
||||
|
||||
sutProvider.GetDependency<IFeatureService>()
|
||||
.IsEnabled(FeatureFlagKeys.UpdateJoinOrganizationEmailTemplate)
|
||||
.Returns(true);
|
||||
|
||||
sutProvider.GetDependency<IUserRepository>()
|
||||
.GetManyByEmailsAsync(Arg.Any<IEnumerable<string>>())
|
||||
.Returns(userExists ? [new User { Email = invite.Email }] : []);
|
||||
|
||||
sutProvider.GetDependency<IUserRepository>()
|
||||
.GetByIdAsync(invitingUser.Id)
|
||||
.Returns(invitingUser);
|
||||
|
||||
sutProvider.GetDependency<IOrgUserInviteTokenableFactory>()
|
||||
.CreateToken(Arg.Any<OrganizationUser>())
|
||||
.Returns(info => new OrgUserInviteTokenable(info.Arg<OrganizationUser>())
|
||||
{
|
||||
ExpirationDate = DateTime.UtcNow.Add(TimeSpan.FromDays(5))
|
||||
});
|
||||
|
||||
// Act
|
||||
await sutProvider.Sut.SendInvitesAsync(new SendInvitesRequest([invite], organization, false, invitingUser.Id));
|
||||
|
||||
// Assert
|
||||
if (userExists)
|
||||
{
|
||||
await sutProvider.GetDependency<IMailer>().Received(1)
|
||||
.SendEmail(Arg.Any<OrganizationInviteEnterpriseTeamsExistingUser>());
|
||||
}
|
||||
else
|
||||
{
|
||||
await sutProvider.GetDependency<IMailer>().Received(1)
|
||||
.SendEmail(Arg.Any<OrganizationInviteEnterpriseTeamsNewUser>());
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(PlanType.FamiliesAnnually, false)]
|
||||
[BitAutoData(PlanType.FamiliesAnnually2025, false)]
|
||||
[BitAutoData(PlanType.FamiliesAnnually, true)]
|
||||
public async Task SendInvitesAsync_WithFeatureFlag_FamiliesPlans_SendsFamiliesTemplate(
|
||||
PlanType planType,
|
||||
bool userExists,
|
||||
Organization organization,
|
||||
OrganizationUser invite,
|
||||
User invitingUser,
|
||||
SutProvider<SendOrganizationInvitesCommand> sutProvider)
|
||||
{
|
||||
SetupSutProvider(sutProvider);
|
||||
|
||||
// Arrange
|
||||
organization.PlanType = planType;
|
||||
invite.OrganizationId = organization.Id;
|
||||
|
||||
sutProvider.GetDependency<IFeatureService>()
|
||||
.IsEnabled(FeatureFlagKeys.UpdateJoinOrganizationEmailTemplate)
|
||||
.Returns(true);
|
||||
|
||||
sutProvider.GetDependency<IUserRepository>()
|
||||
.GetManyByEmailsAsync(Arg.Any<IEnumerable<string>>())
|
||||
.Returns(userExists ? [new User { Email = invite.Email }] : []);
|
||||
|
||||
sutProvider.GetDependency<IUserRepository>()
|
||||
.GetByIdAsync(invitingUser.Id)
|
||||
.Returns(invitingUser);
|
||||
|
||||
sutProvider.GetDependency<IOrgUserInviteTokenableFactory>()
|
||||
.CreateToken(Arg.Any<OrganizationUser>())
|
||||
.Returns(info => new OrgUserInviteTokenable(info.Arg<OrganizationUser>())
|
||||
{
|
||||
ExpirationDate = DateTime.UtcNow.Add(TimeSpan.FromDays(5))
|
||||
});
|
||||
|
||||
// Act
|
||||
await sutProvider.Sut.SendInvitesAsync(new SendInvitesRequest([invite], organization, false, invitingUser.Id));
|
||||
|
||||
// Assert
|
||||
if (userExists)
|
||||
{
|
||||
await sutProvider.GetDependency<IMailer>().Received(1)
|
||||
.SendEmail(Arg.Any<OrganizationInviteFamiliesExistingUser>());
|
||||
}
|
||||
else
|
||||
{
|
||||
await sutProvider.GetDependency<IMailer>().Received(1)
|
||||
.SendEmail(Arg.Any<OrganizationInviteFamiliesNewUser>());
|
||||
}
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task SendInvitesAsync_WithFeatureFlag_FreePlan_SendsFreeTemplate(
|
||||
Organization organization,
|
||||
OrganizationUser invite,
|
||||
User invitingUser,
|
||||
SutProvider<SendOrganizationInvitesCommand> sutProvider)
|
||||
{
|
||||
SetupSutProvider(sutProvider);
|
||||
|
||||
// Arrange
|
||||
organization.PlanType = PlanType.Free;
|
||||
invite.OrganizationId = organization.Id;
|
||||
|
||||
sutProvider.GetDependency<IFeatureService>()
|
||||
.IsEnabled(FeatureFlagKeys.UpdateJoinOrganizationEmailTemplate)
|
||||
.Returns(true);
|
||||
@@ -261,91 +155,10 @@ public class SendOrganizationInvitesCommandTests
|
||||
await sutProvider.Sut.SendInvitesAsync(new SendInvitesRequest([invite], organization, false, invitingUser.Id));
|
||||
|
||||
// Assert
|
||||
await sutProvider.GetDependency<IMailer>().Received(1)
|
||||
.SendEmail(Arg.Any<OrganizationInviteFree>());
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task SendInvitesAsync_WithFeatureFlag_CustomPlan_SendsEnterpriseTemplate(
|
||||
Organization organization,
|
||||
OrganizationUser invite,
|
||||
User invitingUser,
|
||||
SutProvider<SendOrganizationInvitesCommand> sutProvider)
|
||||
{
|
||||
SetupSutProvider(sutProvider);
|
||||
|
||||
// Arrange
|
||||
organization.PlanType = PlanType.Custom;
|
||||
invite.OrganizationId = organization.Id;
|
||||
|
||||
sutProvider.GetDependency<IFeatureService>()
|
||||
.IsEnabled(FeatureFlagKeys.UpdateJoinOrganizationEmailTemplate)
|
||||
.Returns(true);
|
||||
|
||||
sutProvider.GetDependency<IUserRepository>()
|
||||
.GetManyByEmailsAsync(Arg.Any<IEnumerable<string>>())
|
||||
.Returns([]);
|
||||
|
||||
sutProvider.GetDependency<IUserRepository>()
|
||||
.GetByIdAsync(invitingUser.Id)
|
||||
.Returns(invitingUser);
|
||||
|
||||
sutProvider.GetDependency<IOrgUserInviteTokenableFactory>()
|
||||
.CreateToken(Arg.Any<OrganizationUser>())
|
||||
.Returns(info => new OrgUserInviteTokenable(info.Arg<OrganizationUser>())
|
||||
{
|
||||
ExpirationDate = DateTime.UtcNow.Add(TimeSpan.FromDays(5))
|
||||
});
|
||||
|
||||
// Act
|
||||
await sutProvider.Sut.SendInvitesAsync(new SendInvitesRequest([invite], organization, false, invitingUser.Id));
|
||||
|
||||
// Assert
|
||||
await sutProvider.GetDependency<IMailer>().Received(1)
|
||||
.SendEmail(Arg.Any<OrganizationInviteEnterpriseTeamsNewUser>());
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task SendInvitesAsync_WithFeatureFlagEnabled_UsesNewMailer(
|
||||
Organization organization,
|
||||
OrganizationUser invite,
|
||||
User invitingUser,
|
||||
SutProvider<SendOrganizationInvitesCommand> sutProvider)
|
||||
{
|
||||
SetupSutProvider(sutProvider);
|
||||
|
||||
// Arrange
|
||||
organization.PlanType = PlanType.EnterpriseAnnually;
|
||||
sutProvider.GetDependency<IFeatureService>()
|
||||
.IsEnabled(FeatureFlagKeys.UpdateJoinOrganizationEmailTemplate)
|
||||
.Returns(true);
|
||||
|
||||
sutProvider.GetDependency<IUserRepository>()
|
||||
.GetManyByEmailsAsync(Arg.Any<IEnumerable<string>>())
|
||||
.Returns([new User { Email = invite.Email }]);
|
||||
|
||||
sutProvider.GetDependency<IUserRepository>()
|
||||
.GetByIdAsync(invitingUser.Id)
|
||||
.Returns(invitingUser);
|
||||
|
||||
sutProvider.GetDependency<IOrgUserInviteTokenableFactory>()
|
||||
.CreateToken(Arg.Any<OrganizationUser>())
|
||||
.Returns(info => new OrgUserInviteTokenable(info.Arg<OrganizationUser>())
|
||||
{
|
||||
ExpirationDate = DateTime.UtcNow.Add(TimeSpan.FromDays(5))
|
||||
});
|
||||
|
||||
// Act
|
||||
await sutProvider.Sut.SendInvitesAsync(new SendInvitesRequest([invite], organization, false, invitingUser.Id));
|
||||
|
||||
// Assert - verify new mailer is called, not legacy mail service
|
||||
await sutProvider.GetDependency<IMailer>()
|
||||
.Received(1)
|
||||
.SendEmail(Arg.Any<OrganizationInviteEnterpriseTeamsExistingUser>());
|
||||
|
||||
await sutProvider.GetDependency<IMailService>()
|
||||
.DidNotReceive()
|
||||
.SendOrganizationInviteEmailsAsync(Arg.Any<OrganizationInvitesInfo>());
|
||||
await sutProvider.GetDependency<IMailService>().Received(1)
|
||||
.SendUpdatedOrganizationInviteEmailsAsync(Arg.Is<OrganizationInvitesInfo>(info =>
|
||||
info.OrgUserTokenPairs.Any(p => p.OrgUser.Email == invite.Email) &&
|
||||
info.InviterEmail == invitingUser.Email));
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
@@ -377,10 +190,6 @@ public class SendOrganizationInvitesCommandTests
|
||||
await sutProvider.GetDependency<IMailService>()
|
||||
.Received(1)
|
||||
.SendOrganizationInviteEmailsAsync(Arg.Any<OrganizationInvitesInfo>());
|
||||
|
||||
await sutProvider.GetDependency<IMailer>()
|
||||
.DidNotReceive()
|
||||
.SendEmail(Arg.Any<BaseMail<OrganizationInviteBaseView>>());
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
@@ -417,9 +226,10 @@ public class SendOrganizationInvitesCommandTests
|
||||
await sutProvider.Sut.SendInvitesAsync(new SendInvitesRequest([invite], organization, false, invitingUser.Id));
|
||||
|
||||
// Assert
|
||||
await sutProvider.GetDependency<IMailer>().Received(1)
|
||||
.SendEmail(Arg.Is<OrganizationInviteEnterpriseTeamsNewUser>(mail =>
|
||||
mail.View.InviterEmail == invitingUser.Email));
|
||||
await sutProvider.GetDependency<IMailService>().Received(1)
|
||||
.SendUpdatedOrganizationInviteEmailsAsync(Arg.Is<OrganizationInvitesInfo>(info =>
|
||||
info.OrgUserTokenPairs.Any(p => p.OrgUser.Email == invite.Email) &&
|
||||
info.InviterEmail == invitingUser.Email));
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
@@ -451,9 +261,10 @@ public class SendOrganizationInvitesCommandTests
|
||||
await sutProvider.Sut.SendInvitesAsync(new SendInvitesRequest([invite], organization, false, null));
|
||||
|
||||
// Assert
|
||||
await sutProvider.GetDependency<IMailer>().Received(1)
|
||||
.SendEmail(Arg.Is<OrganizationInviteEnterpriseTeamsNewUser>(mail =>
|
||||
mail.View.InviterEmail == null));
|
||||
await sutProvider.GetDependency<IMailService>().Received(1)
|
||||
.SendUpdatedOrganizationInviteEmailsAsync(Arg.Is<OrganizationInvitesInfo>(info =>
|
||||
info.OrgUserTokenPairs.Any(p => p.OrgUser.Email == invite.Email) &&
|
||||
info.InviterEmail == null));
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
@@ -491,15 +302,15 @@ public class SendOrganizationInvitesCommandTests
|
||||
await sutProvider.Sut.SendInvitesAsync(new SendInvitesRequest([invite], organization, false, nonExistentUserId));
|
||||
|
||||
// Assert
|
||||
await sutProvider.GetDependency<IMailer>().Received(1)
|
||||
.SendEmail(Arg.Is<OrganizationInviteEnterpriseTeamsNewUser>(mail =>
|
||||
mail.View.InviterEmail == null));
|
||||
await sutProvider.GetDependency<IMailService>().Received(1)
|
||||
.SendUpdatedOrganizationInviteEmailsAsync(Arg.Is<OrganizationInvitesInfo>(info =>
|
||||
info.OrgUserTokenPairs.Any(p => p.OrgUser.Email == invite.Email) &&
|
||||
info.InviterEmail == null));
|
||||
}
|
||||
|
||||
private void SetupSutProvider(SutProvider<SendOrganizationInvitesCommand> sutProvider)
|
||||
{
|
||||
sutProvider.SetDependency(_orgUserInviteTokenDataFactory, "orgUserInviteTokenDataFactory");
|
||||
sutProvider.SetDependency(new CoreGlobalSettings { BaseServiceUri = new CoreGlobalSettings.BaseServiceUriSettings(new CoreGlobalSettings()) }, "globalSettings");
|
||||
sutProvider.Create();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.AdminConsole.Models.Mail.Mailer.OrganizationConfirmation;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.OrganizationConfirmation;
|
||||
using Bit.Core.Billing.Enums;
|
||||
using Bit.Core.Platform.Mail.Mailer;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Test.AutoFixture.OrganizationFixtures;
|
||||
using Bit.Test.Common.AutoFixture;
|
||||
using Bit.Test.Common.AutoFixture.Attributes;
|
||||
@@ -16,230 +15,39 @@ public class SendOrganizationConfirmationCommandTests
|
||||
{
|
||||
[Theory]
|
||||
[OrganizationCustomize, BitAutoData]
|
||||
public async Task SendConfirmationAsync_EnterpriseOrganization_SendsEnterpriseTeamsEmail(
|
||||
public async Task SendConfirmationAsync_EnterpriseOrg_CallsUpdatedConfirmedEmail(
|
||||
Organization organization,
|
||||
string userEmail,
|
||||
SutProvider<SendOrganizationConfirmationCommand> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
organization.PlanType = PlanType.EnterpriseAnnually;
|
||||
organization.Name = "Test Enterprise Org";
|
||||
|
||||
// Act
|
||||
await sutProvider.Sut.SendConfirmationAsync(organization, userEmail, false);
|
||||
await sutProvider.Sut.SendConfirmationAsync(organization, userEmail, true);
|
||||
|
||||
// Assert
|
||||
await sutProvider.GetDependency<IMailer>().Received(1)
|
||||
.SendEmail(Arg.Is<OrganizationConfirmationEnterpriseTeams>(mail =>
|
||||
mail.ToEmails.Contains(userEmail) &&
|
||||
mail.ToEmails.Count() == 1 &&
|
||||
mail.View.OrganizationName == organization.Name &&
|
||||
mail.Subject == GetSubject(organization.Name)));
|
||||
await sutProvider.GetDependency<IMailService>()
|
||||
.Received(1)
|
||||
.SendUpdatedOrganizationConfirmedEmailAsync(organization, userEmail, true);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[OrganizationCustomize, BitAutoData]
|
||||
public async Task SendConfirmationAsync_TeamsOrganization_SendsEnterpriseTeamsEmail(
|
||||
Organization organization,
|
||||
string userEmail,
|
||||
SutProvider<SendOrganizationConfirmationCommand> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
organization.PlanType = PlanType.TeamsAnnually;
|
||||
organization.Name = "Test Teams Org";
|
||||
|
||||
// Act
|
||||
await sutProvider.Sut.SendConfirmationAsync(organization, userEmail, false);
|
||||
|
||||
// Assert
|
||||
await sutProvider.GetDependency<IMailer>().Received(1)
|
||||
.SendEmail(Arg.Is<OrganizationConfirmationEnterpriseTeams>(mail =>
|
||||
mail.ToEmails.Contains(userEmail) &&
|
||||
mail.ToEmails.Count() == 1 &&
|
||||
mail.View.OrganizationName == organization.Name &&
|
||||
mail.Subject == GetSubject(organization.Name)));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[OrganizationCustomize, BitAutoData]
|
||||
public async Task SendConfirmationAsync_FamilyOrganization_SendsFamilyFreeEmail(
|
||||
public async Task SendConfirmationAsync_FamiliesOrg_CallsUpdatedConfirmedEmail(
|
||||
Organization organization,
|
||||
string userEmail,
|
||||
SutProvider<SendOrganizationConfirmationCommand> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
organization.PlanType = PlanType.FamiliesAnnually;
|
||||
organization.Name = "Test Family Org";
|
||||
|
||||
// Act
|
||||
await sutProvider.Sut.SendConfirmationAsync(organization, userEmail, false);
|
||||
|
||||
// Assert
|
||||
await sutProvider.GetDependency<IMailer>().Received(1)
|
||||
.SendEmail(Arg.Is<OrganizationConfirmationFamilyFree>(mail =>
|
||||
mail.ToEmails.Contains(userEmail) &&
|
||||
mail.ToEmails.Count() == 1 &&
|
||||
mail.View.OrganizationName == organization.Name &&
|
||||
mail.Subject == GetSubject(organization.Name)));
|
||||
await sutProvider.GetDependency<IMailService>()
|
||||
.Received(1)
|
||||
.SendUpdatedOrganizationConfirmedEmailAsync(organization, userEmail, false);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[OrganizationCustomize, BitAutoData]
|
||||
public async Task SendConfirmationAsync_FreeOrganization_SendsFamilyFreeEmail(
|
||||
Organization organization,
|
||||
string userEmail,
|
||||
SutProvider<SendOrganizationConfirmationCommand> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
organization.PlanType = PlanType.Free;
|
||||
organization.Name = "Test Free Org";
|
||||
|
||||
// Act
|
||||
await sutProvider.Sut.SendConfirmationAsync(organization, userEmail, false);
|
||||
|
||||
// Assert
|
||||
await sutProvider.GetDependency<IMailer>().Received(1)
|
||||
.SendEmail(Arg.Is<OrganizationConfirmationFamilyFree>(mail =>
|
||||
mail.ToEmails.Contains(userEmail) &&
|
||||
mail.ToEmails.Count() == 1 &&
|
||||
mail.View.OrganizationName == organization.Name &&
|
||||
mail.Subject == GetSubject(organization.Name)));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[OrganizationCustomize, BitAutoData]
|
||||
public async Task SendConfirmationsAsync_MultipleUsers_SendsSingleEmail(
|
||||
Organization organization,
|
||||
List<string> userEmails,
|
||||
SutProvider<SendOrganizationConfirmationCommand> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
organization.PlanType = PlanType.EnterpriseAnnually;
|
||||
organization.Name = "Test Enterprise Org";
|
||||
|
||||
// Act
|
||||
await sutProvider.Sut.SendConfirmationsAsync(organization, userEmails, false);
|
||||
|
||||
// Assert
|
||||
await sutProvider.GetDependency<IMailer>().Received(1)
|
||||
.SendEmail(Arg.Is<OrganizationConfirmationEnterpriseTeams>(mail =>
|
||||
mail.ToEmails.SequenceEqual(userEmails) &&
|
||||
mail.View.OrganizationName == organization.Name));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[OrganizationCustomize, BitAutoData]
|
||||
public async Task SendConfirmationsAsync_EmptyUserList_DoesNotSendEmail(
|
||||
Organization organization,
|
||||
SutProvider<SendOrganizationConfirmationCommand> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
organization.PlanType = PlanType.EnterpriseAnnually;
|
||||
organization.Name = "Test Enterprise Org";
|
||||
|
||||
// Act
|
||||
await sutProvider.Sut.SendConfirmationsAsync(organization, [], false);
|
||||
|
||||
// Assert
|
||||
await sutProvider.GetDependency<IMailer>().DidNotReceive()
|
||||
.SendEmail(Arg.Any<OrganizationConfirmationEnterpriseTeams>());
|
||||
await sutProvider.GetDependency<IMailer>().DidNotReceive()
|
||||
.SendEmail(Arg.Any<OrganizationConfirmationFamilyFree>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[OrganizationCustomize, BitAutoData]
|
||||
public async Task SendConfirmationAsync_HtmlEncodedOrganizationName_DecodesNameCorrectly(
|
||||
Organization organization,
|
||||
string userEmail,
|
||||
SutProvider<SendOrganizationConfirmationCommand> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
organization.PlanType = PlanType.EnterpriseAnnually;
|
||||
organization.Name = "Test & Company";
|
||||
var expectedDecodedName = "Test & Company";
|
||||
|
||||
// Act
|
||||
await sutProvider.Sut.SendConfirmationAsync(organization, userEmail, false);
|
||||
|
||||
// Assert
|
||||
await sutProvider.GetDependency<IMailer>().Received(1)
|
||||
.SendEmail(Arg.Is<OrganizationConfirmationEnterpriseTeams>(mail =>
|
||||
mail.View.OrganizationName == expectedDecodedName));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[OrganizationCustomize, BitAutoData]
|
||||
public async Task SendConfirmationAsync_AllEnterpriseTeamsPlanTypes_SendsEnterpriseTeamsEmail(
|
||||
Organization organization,
|
||||
string userEmail,
|
||||
SutProvider<SendOrganizationConfirmationCommand> sutProvider)
|
||||
{
|
||||
// Test all Enterprise and Teams plan types
|
||||
var enterpriseTeamsPlanTypes = new[]
|
||||
{
|
||||
PlanType.TeamsMonthly2019, PlanType.TeamsAnnually2019,
|
||||
PlanType.TeamsMonthly2020, PlanType.TeamsAnnually2020,
|
||||
PlanType.TeamsMonthly2023, PlanType.TeamsAnnually2023,
|
||||
PlanType.TeamsStarter2023, PlanType.TeamsMonthly,
|
||||
PlanType.TeamsAnnually, PlanType.TeamsStarter,
|
||||
PlanType.EnterpriseMonthly2019, PlanType.EnterpriseAnnually2019,
|
||||
PlanType.EnterpriseMonthly2020, PlanType.EnterpriseAnnually2020,
|
||||
PlanType.EnterpriseMonthly2023, PlanType.EnterpriseAnnually2023,
|
||||
PlanType.EnterpriseMonthly, PlanType.EnterpriseAnnually
|
||||
};
|
||||
|
||||
foreach (var planType in enterpriseTeamsPlanTypes)
|
||||
{
|
||||
// Arrange
|
||||
organization.PlanType = planType;
|
||||
organization.Name = "Test Org";
|
||||
sutProvider.GetDependency<IMailer>().ClearReceivedCalls();
|
||||
|
||||
// Act
|
||||
await sutProvider.Sut.SendConfirmationAsync(organization, userEmail, false);
|
||||
|
||||
// Assert
|
||||
await sutProvider.GetDependency<IMailer>().Received(1)
|
||||
.SendEmail(Arg.Any<OrganizationConfirmationEnterpriseTeams>());
|
||||
await sutProvider.GetDependency<IMailer>().DidNotReceive()
|
||||
.SendEmail(Arg.Any<OrganizationConfirmationFamilyFree>());
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[OrganizationCustomize, BitAutoData]
|
||||
public async Task SendConfirmationAsync_AllFamilyFreePlanTypes_SendsFamilyFreeEmail(
|
||||
Organization organization,
|
||||
string userEmail,
|
||||
SutProvider<SendOrganizationConfirmationCommand> sutProvider)
|
||||
{
|
||||
// Test all Family, Free, and Custom plan types
|
||||
var familyFreePlanTypes = new[]
|
||||
{
|
||||
PlanType.Free, PlanType.FamiliesAnnually2019,
|
||||
PlanType.FamiliesAnnually2025, PlanType.FamiliesAnnually,
|
||||
PlanType.Custom
|
||||
};
|
||||
|
||||
foreach (var planType in familyFreePlanTypes)
|
||||
{
|
||||
// Arrange
|
||||
organization.PlanType = planType;
|
||||
organization.Name = "Test Org";
|
||||
sutProvider.GetDependency<IMailer>().ClearReceivedCalls();
|
||||
|
||||
// Act
|
||||
await sutProvider.Sut.SendConfirmationAsync(organization, userEmail, false);
|
||||
|
||||
// Assert
|
||||
await sutProvider.GetDependency<IMailer>().Received(1)
|
||||
.SendEmail(Arg.Any<OrganizationConfirmationFamilyFree>());
|
||||
await sutProvider.GetDependency<IMailer>().DidNotReceive()
|
||||
.SendEmail(Arg.Any<OrganizationConfirmationEnterpriseTeams>());
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetSubject(string organizationName) => $"You can now access items from {organizationName}";
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user