using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using LCU.Library.Internal.MemberPreferencesApiModels.Entities; using LCU.Library.Internal.MemberPreferencesApiModels.Enums; using FluentAssertions; using NUnit.Framework; using LCU.Library.Internal.MemberPreferencesApiModels.Models; using LCU.API.Internal.MemberPreferencesApi.Models.EmailPolicies; namespace LCU.Library.Internal.MemberPreferencesApiModels.UnitTests.Policies.Email.FailedToSend { public abstract class SixtyDaysUndeliverableEmailPolicyTest { protected abstract SixtyDaysUndeliverableEmailPolicy Policy { get; } protected IAuditableChanges AuditableChanges => _auditableChanges; protected IMemberPreferences MemberPreferences => _memberPreferences; protected abstract void SetEmailStatus(MemberOptInSettings settings, EmailStatus status); protected abstract void SetFirstSent(MemberOptInSettings settings, DateTime firstSent); protected abstract void SetLastSend(MemberOptInSettings settings, DateTime lastSent); protected abstract void SetEligibleForPreferenceFlip(MemberOptInSettings settings); protected abstract string GetPreference(MemberOptInSettings settings); private readonly FakeAuditableChanges _auditableChanges = new FakeAuditableChanges(); private readonly FakeMemberPreferences _memberPreferences = new FakeMemberPreferences(); [SetUp] public void SetUp() { _memberPreferences.Changes.Clear(); } [Test] public async Task Apply_NotFailingDelivery_ReturnsFalse() { var settings = SettingsFactory(); SetEmailStatus(settings, EmailStatus.DeliveredSuccessfully); var originalSettings = Clone(settings); var anyChanges = await Policy.Apply(settings, true); Assert.That(anyChanges, Is.False); Assert.That(_memberPreferences.Changes.Any(), Is.False); settings.Should().BeEquivalentTo(originalSettings); } [Test] public async Task Apply_FailingDeliveryForLessThanSixtyDays_ReturnsFalse() { var settings = SettingsFactory(); SetEmailStatus(settings, EmailStatus.FailingDelivery); SetFirstSent(settings, DateTime.Now.AddDays(-59)); SetLastSend(settings, DateTime.Now); var originalSettings = Clone(settings); var anyChanges = await Policy.Apply(settings, true); Assert.That(anyChanges, Is.False); Assert.That(_memberPreferences.Changes.Any(), Is.False); settings.Should().BeEquivalentTo(originalSettings); } [Test] public async Task Apply_FailingDeliveryForSixtyDaysOrMore_ReturnsTrueAndSetsToPaper() { var settings = SettingsFactory(); SetEmailStatus(settings, EmailStatus.FailingDelivery); SetFirstSent(settings, DateTime.Now.AddDays(-60)); SetLastSend(settings, DateTime.Now); SetEligibleForPreferenceFlip(settings); var originalSettings = Clone(settings); var anyChanges = await Policy.Apply(settings, true); var preference = GetPreference(settings); Assert.That(anyChanges, Is.True); settings.Should().BeEquivalentTo ( originalSettings, except => except .Excluding(s => s.LastUpdatedBy) .Excluding(s => s.UniversalOptIn) .Excluding(s => s.ENotifications) .Excluding(s => s.EStatements) ); Assert.That(preference, Is.EqualTo(DeliveryPreference.Paper)); Assert.That(settings.LastUpdatedBy, Is.EqualTo("BounceBackLimitReached")); Assert.That(_memberPreferences.Changes.Count(p => p.Value == DeliveryPreference.Paper && p.UserId == settings.UserId && p.LastUpdatedBy == "BounceBackLimitReached"), Is.EqualTo(1)); } [Test] public async Task Apply_FailingDeliveryForSixtyDaysOrMore_FeatureFlagReturnsFalse() { var settings = SettingsFactory(); SetEmailStatus(settings, EmailStatus.FailingDelivery); SetFirstSent(settings, DateTime.Now.AddDays(-60)); SetLastSend(settings, DateTime.Now); var originalSettings = Clone(settings); var anyChanges = await Policy.Apply(settings, false); var preference = GetPreference(settings); Assert.That(anyChanges, Is.False); Assert.That(_memberPreferences.Changes.Any(), Is.False); settings.Should().BeEquivalentTo(originalSettings); Assert.That(_memberPreferences.Changes.Count(p => p.Value == DeliveryPreference.Paper && p.UserId == settings.UserId && p.LastUpdatedBy == "BounceBackLimitReached"), Is.EqualTo(0)); } [Test] public async Task Apply_FailingDeliveryForSixtyDaysOrMore_SetsTrackingToBounceBackSystem() { var settings = SettingsFactory(); SetEmailStatus(settings, EmailStatus.FailingDelivery); SetFirstSent(settings, DateTime.Now.AddDays(-60)); SetLastSend(settings, DateTime.Now); SetEligibleForPreferenceFlip(settings); await Policy.Apply(settings, true); Assert.That(settings.LastUpdatedBy, Is.EqualTo("BounceBackLimitReached")); Assert.That(_auditableChanges.SystemModifiedAuditableEntities.ContainsKey(settings), Is.True); Assert.That(_auditableChanges.SystemModifiedAuditableEntities[settings], Is.EqualTo("BounceBackLimitReached")); } private static MemberOptInSettings SettingsFactory() => new MemberOptInSettings { LastUpdatedBy = Guid.NewGuid().ToString(), UniversalOptIn = DeliveryPreference.Electronic, UnifiedOptInEmailStatus = EmailStatus.DeliveredSuccessfully, UnifiedOptInEmailFirstSent = DateTime.Now, UnifiedOptInEmailLastSent = DateTime.Now, ENotifications = DeliveryPreference.Electronic, ENotificationsEmailStatus = EmailStatus.DeliveredSuccessfully, ENotificationsEmailFirstSent = DateTime.Now, ENotificationsEmailLastSent = DateTime.Now, EStatements = DeliveryPreference.Electronic, EStatementsEmailStatus = EmailStatus.DeliveredSuccessfully, EStatementsEmailFirstSent = DateTime.Now, EStatementsEmailLastSent = DateTime.Now }; private static MemberOptInSettings Clone(MemberOptInSettings settings) => new MemberOptInSettings { LastUpdatedBy = settings.LastUpdatedBy, UniversalOptIn = settings.UniversalOptIn, UnifiedOptInEmailStatus = settings.UnifiedOptInEmailStatus, UnifiedOptInEmailFirstSent = settings.UnifiedOptInEmailFirstSent, UnifiedOptInEmailLastSent = settings.UnifiedOptInEmailLastSent, ENotifications = settings.ENotifications, ENotificationsEmailStatus = settings.ENotificationsEmailStatus, ENotificationsEmailFirstSent = settings.ENotificationsEmailFirstSent, ENotificationsEmailLastSent = settings.ENotificationsEmailLastSent, EStatements = settings.EStatements, EStatementsEmailStatus = settings.EStatementsEmailStatus, EStatementsEmailFirstSent = settings.EStatementsEmailFirstSent, EStatementsEmailLastSent = settings.EStatementsEmailLastSent }; private class FakeAuditableChanges : IAuditableChanges { public IDictionary SystemModifiedAuditableEntities { get; } = new Dictionary(); public void SystemModified(Auditable entity, string modifiedBy) { SystemModifiedAuditableEntities[entity] = modifiedBy; } } private class FakeMemberPreferences : IMemberPreferences { public IList Changes { get; }= new List(); public Task Add(MemberPreference preferenceChange) { Changes.Add(preferenceChange); return Task.CompletedTask; } } } }