public async Task <NotificationSendingResult> SendAsync(NotificationMessage message, UserSettings settings) { var result = new NotificationSendingResult(SenderType); if (!ShouldSend(message.Event, settings, result)) { return(result); } var notification = _messageFactory.Create(message, settings); var validator = _validatorProvider.GetValidator(notification); var validationResult = await validator.ValidateAsync(notification); if (!validationResult.IsValid) { Logger.LogWarning($"Invalid {SenderType} notification message state", validationResult.Errors); result.Errors.AddRange(validationResult.Errors.Select(x => x.ErrorMessage)); return(result); } await PerformSendingAsync(notification, settings, result); return(result); }
public async Task WhenNoSuccessfulSendsThenHistoryRecordNotCreatedTest() { var userId = Guid.NewGuid().ToString(); var store = new Mock <ISettingsDataStore>(); store.Setup(x => x.FindAsync(It.Is <string>(s => s == userId))) .ReturnsAsync(new UserSettings { UserId = userId }); var historyStore = new Mock <INotificationHistoryDataStore>(); var failedResult1 = new NotificationSendingResult(NotificationType.Email); failedResult1.Errors.Add("Error1"); var sender1 = new Mock <INotificationSender>(); sender1.Setup(x => x.SendAsync(It.IsAny <NotificationMessage>(), It.IsAny <UserSettings>())) .ReturnsAsync(failedResult1); var failedResult2 = new NotificationSendingResult(NotificationType.Push); failedResult2.Errors.Add("Error2"); var sender2 = new Mock <INotificationSender>(); sender2.Setup(x => x.SendAsync(It.IsAny <NotificationMessage>(), It.IsAny <UserSettings>())) .ReturnsAsync(failedResult2); var senders = new List <INotificationSender> { sender1.Object, sender2.Object }; var service = new NotificationService(store.Object, senders, historyStore.Object, DefaultMapper); var result = await service.PostAsync(new SendNotificationRequest { EventType = NotificationEvent.ArticleCreated, RecipientUserId = userId }); Assert.NotNull(result); historyStore.Verify(x => x.SaveAsync(It.IsAny <NotificationRecord>()), Times.Never); sender1.Verify(x => x.SendAsync(It.IsAny <NotificationMessage>(), It.IsAny <UserSettings>()), Times.Once); sender2.Verify(x => x.SendAsync(It.IsAny <NotificationMessage>(), It.IsAny <UserSettings>()), Times.Once); Assert.Null(result.NotificationRecordId); Assert.Equal(2, result.Results.Count); }
protected abstract Task PerformSendingAsync(TMessage message, UserSettings settings, NotificationSendingResult result);
protected virtual bool ShouldSend(NotificationEvent @event, UserSettings settings, NotificationSendingResult result) { var configuration = NotificationEventConfiguration.Find(SenderType, @event); if (configuration == null) { result.Skip(); return(false); } if (configuration.IsMandatory) { return(true); } var eventSetting = settings.Settings.FirstOrDefault(s => s.Type == SenderType && s.Event == @event); var isEnabled = eventSetting?.Enabled ?? configuration.IsEnabledByDefault; if (!isEnabled) { result.Skip(); } return(isEnabled); }
public async Task WhenSenderSucceedsThenRecordCreatedTest() { var userId = Guid.NewGuid().ToString(); var request = new SendNotificationRequest { EventType = NotificationEvent.ArticleCreated, RecipientUserId = userId, Parameters = new Dictionary <string, object> { { "testKey", "testValue" } } }; var store = new Mock <ISettingsDataStore>(); store.Setup(x => x.FindAsync(It.Is <string>(s => s == userId))) .ReturnsAsync(new UserSettings { Id = Guid.NewGuid(), UserId = userId }); NotificationRecord newRecord = null; var historyStore = new Mock <INotificationHistoryDataStore>(); historyStore.Setup(x => x.SaveAsync(It.IsAny <NotificationRecord>())) .Callback <NotificationRecord>(record => { newRecord = record; newRecord.Id = Guid.NewGuid(); }) .ReturnsAsync(() => newRecord); var skippedResult = new NotificationSendingResult(NotificationType.Email); skippedResult.Skip(); var sender1 = new Mock <INotificationSender>(); sender1.Setup(x => x.SendAsync(It.IsAny <NotificationMessage>(), It.IsAny <UserSettings>())) .ReturnsAsync(skippedResult); var successfulResult = new NotificationSendingResult(NotificationType.Push); var sender2 = new Mock <INotificationSender>(); sender2.Setup(x => x.SendAsync(It.IsAny <NotificationMessage>(), It.IsAny <UserSettings>())) .ReturnsAsync(successfulResult); var senders = new List <INotificationSender> { sender1.Object, sender2.Object }; var service = new NotificationService(store.Object, senders, historyStore.Object, DefaultMapper); var result = await service.PostAsync(request); Assert.NotNull(result); historyStore.Verify(x => x.SaveAsync(It.IsAny <NotificationRecord>()), Times.Once); sender1.Verify(x => x.SendAsync(It.IsAny <NotificationMessage>(), It.IsAny <UserSettings>()), Times.Once); sender2.Verify(x => x.SendAsync(It.IsAny <NotificationMessage>(), It.IsAny <UserSettings>()), Times.Once); Assert.NotNull(result.NotificationRecordId); Assert.Equal(1, result.Results.Count); Assert.DoesNotContain(skippedResult, result.Results); Assert.Contains(successfulResult, result.Results); Assert.Equal(newRecord.Id, result.NotificationRecordId); Assert.Equal(request.RecipientUserId, newRecord.OwnerUserId); Assert.Equal(request.Parameters, newRecord.Parameters); }
protected override bool ShouldSend(NotificationEvent @event, UserSettings settings, NotificationSendingResult result) { if (string.IsNullOrWhiteSpace(settings.PhoneNumber)) { result.Errors.Add(PhoneNumberIsNotConfiguredErrorMessage); return(false); } return(base.ShouldSend(@event, settings, result)); }
protected override async Task PerformSendingAsync(ISmsNotification message, UserSettings settings, NotificationSendingResult result) { try { await _sender.SendAsync(message); } catch (SmsSenderException exception) { Logger.LogError(exception, ExceptionWhileSendingSmsMessage); if (exception.Errors != null && exception.Errors.Any()) { result.Errors.AddRange(exception.Errors.Keys); } else { result.Errors.Add(UnspecifiedErrorMessage); } } }
protected override async Task PerformSendingAsync(PushNotificationMessage message, UserSettings settings, NotificationSendingResult result) { try { var isSent = await _sender.SendAsync(message, TagHelper.GetUserTag(settings.UserId)); if (!isSent) { Logger.LogWarning("Failed to send push notification"); result.Errors.Add("Unspecified error"); } } catch (ValidationException ex) { Logger.LogError(ex, "Exception while validating push message"); result.Errors.Add("Validation Error"); } catch (PushNotificationException ex) { Logger.LogError(ex, "Exception while sending push notification"); result.Errors.Add("Unspecified error"); } }
protected override bool ShouldSend(NotificationEvent @event, UserSettings settings, NotificationSendingResult result) { if (string.IsNullOrWhiteSpace(settings.Email)) { result.Errors.Add("User email address is not configured"); return(false); } return(base.ShouldSend(@event, settings, result)); }
protected override async Task PerformSendingAsync(IEmailNotification message, UserSettings settings, NotificationSendingResult result) { try { await _sender.SendAsync(message); } catch (EmailSenderException ex) { Logger.LogError(ex, "Exception while sending email notification"); result.Errors.Add("Unspecified error"); } }