-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e0d46d2
commit ab370a3
Showing
2 changed files
with
223 additions
and
26 deletions.
There are no files selected for viewing
76 changes: 76 additions & 0 deletions
76
test/Core.Test/Models/Api/Request/PushSendRequestModelTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
#nullable enable | ||
using System.ComponentModel.DataAnnotations; | ||
using Bit.Core.Enums; | ||
using Bit.Core.Models.Api; | ||
using Xunit; | ||
|
||
namespace Bit.Core.Test.Models.Api.Request; | ||
|
||
public class PushSendRequestModelTests | ||
{ | ||
[Theory] | ||
[InlineData(null, null)] | ||
[InlineData(null, "")] | ||
[InlineData(null, " ")] | ||
[InlineData("", null)] | ||
[InlineData(" ", null)] | ||
[InlineData("", "")] | ||
[InlineData(" ", " ")] | ||
public void Validate_UserIdOrganizationIdNullOrEmpty_Invalid(string? userId, string? organizationId) | ||
{ | ||
var model = new PushSendRequestModel | ||
{ | ||
UserId = userId, | ||
OrganizationId = organizationId, | ||
Type = PushType.SyncCiphers, | ||
Payload = "test" | ||
}; | ||
|
||
var results = Validate(model); | ||
|
||
Assert.Single(results); | ||
Assert.Contains(results, result => result.ErrorMessage == "UserId or OrganizationId is required."); | ||
} | ||
|
||
[Fact] | ||
public void Validate_RequiredPayloadFieldNotProvided_Invalid() | ||
{ | ||
var model = new PushSendRequestModel | ||
{ | ||
UserId = Guid.NewGuid().ToString(), | ||
OrganizationId = Guid.NewGuid().ToString(), | ||
Type = PushType.SyncCiphers | ||
}; | ||
|
||
var results = Validate(model); | ||
|
||
Assert.Single(results); | ||
Assert.Contains(results, result => result.ErrorMessage == "The Payload field is required."); | ||
} | ||
|
||
[Fact] | ||
public void Validate_AllFieldsPresent_Valid() | ||
{ | ||
var model = new PushSendRequestModel | ||
{ | ||
UserId = Guid.NewGuid().ToString(), | ||
OrganizationId = Guid.NewGuid().ToString(), | ||
Type = PushType.SyncCiphers, | ||
Payload = "test payload", | ||
Identifier = Guid.NewGuid().ToString(), | ||
ClientType = ClientType.All, | ||
DeviceId = Guid.NewGuid().ToString() | ||
}; | ||
|
||
var results = Validate(model); | ||
|
||
Assert.Empty(results); | ||
} | ||
|
||
private static List<ValidationResult> Validate(PushSendRequestModel model) | ||
{ | ||
var results = new List<ValidationResult>(); | ||
Validator.TryValidateObject(model, new ValidationContext(model), results); | ||
return results; | ||
} | ||
} |
173 changes: 147 additions & 26 deletions
173
test/Core.Test/NotificationHub/NotificationHubPushNotificationServiceTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,42 +1,163 @@ | ||
using Bit.Core.NotificationHub; | ||
using System.Text.Json; | ||
using Bit.Core.Enums; | ||
using Bit.Core.Models; | ||
using Bit.Core.Models.Data; | ||
using Bit.Core.NotificationCenter.Entities; | ||
using Bit.Core.NotificationHub; | ||
using Bit.Core.Repositories; | ||
using Bit.Core.Services; | ||
using Microsoft.AspNetCore.Http; | ||
using Microsoft.Extensions.Logging; | ||
using Bit.Core.Test.NotificationCenter.AutoFixture; | ||
using Bit.Test.Common.AutoFixture; | ||
using Bit.Test.Common.AutoFixture.Attributes; | ||
using NSubstitute; | ||
using Xunit; | ||
|
||
namespace Bit.Core.Test.NotificationHub; | ||
|
||
[SutProviderCustomize] | ||
public class NotificationHubPushNotificationServiceTests | ||
{ | ||
private readonly NotificationHubPushNotificationService _sut; | ||
[Theory] | ||
[BitAutoData] | ||
[NotificationCustomize] | ||
public async void PushSyncNotificationAsync_Global_NotSent( | ||
SutProvider<NotificationHubPushNotificationService> sutProvider, Notification notification) | ||
{ | ||
await sutProvider.Sut.PushSyncNotificationAsync(notification); | ||
|
||
await sutProvider.GetDependency<INotificationHubPool>() | ||
.Received(0) | ||
.AllClients | ||
.Received(0) | ||
.SendTemplateNotificationAsync(Arg.Any<IDictionary<string, string>>(), Arg.Any<string>()); | ||
await sutProvider.GetDependency<IInstallationDeviceRepository>() | ||
.Received(0) | ||
.UpsertAsync(Arg.Any<InstallationDeviceEntity>()); | ||
} | ||
|
||
[Theory] | ||
[BitAutoData(false)] | ||
[BitAutoData(true)] | ||
[NotificationCustomize(false)] | ||
public async void PushSyncNotificationAsync_UserIdProvidedClientTypeAll_SentToUser( | ||
bool organizationIdNull, SutProvider<NotificationHubPushNotificationService> sutProvider, | ||
Notification notification) | ||
{ | ||
if (organizationIdNull) | ||
{ | ||
notification.OrganizationId = null; | ||
} | ||
|
||
notification.ClientType = ClientType.All; | ||
var expectedSyncNotification = ToSyncNotificationPushNotification(notification); | ||
|
||
await sutProvider.Sut.PushSyncNotificationAsync(notification); | ||
|
||
await AssertSendTemplateNotificationAsync(sutProvider, PushType.SyncNotification, expectedSyncNotification, | ||
$"(template:payload_userId:{notification.UserId})"); | ||
await sutProvider.GetDependency<IInstallationDeviceRepository>() | ||
.Received(0) | ||
.UpsertAsync(Arg.Any<InstallationDeviceEntity>()); | ||
} | ||
|
||
[Theory] | ||
[BitAutoData(false, ClientType.Browser)] | ||
[BitAutoData(false, ClientType.Desktop)] | ||
[BitAutoData(false, ClientType.Web)] | ||
[BitAutoData(false, ClientType.Mobile)] | ||
[BitAutoData(true, ClientType.Browser)] | ||
[BitAutoData(true, ClientType.Desktop)] | ||
[BitAutoData(true, ClientType.Web)] | ||
[BitAutoData(true, ClientType.Mobile)] | ||
[NotificationCustomize(false)] | ||
public async void PushSyncNotificationAsync_UserIdProvidedClientTypeNotAll_SentToUser(bool organizationIdNull, | ||
ClientType clientType, SutProvider<NotificationHubPushNotificationService> sutProvider, | ||
Notification notification) | ||
{ | ||
if (organizationIdNull) | ||
{ | ||
notification.OrganizationId = null; | ||
} | ||
|
||
notification.ClientType = clientType; | ||
var expectedSyncNotification = ToSyncNotificationPushNotification(notification); | ||
|
||
await sutProvider.Sut.PushSyncNotificationAsync(notification); | ||
|
||
await AssertSendTemplateNotificationAsync(sutProvider, PushType.SyncNotification, expectedSyncNotification, | ||
$"(template:payload_userId:{notification.UserId} && clientType:{clientType})"); | ||
await sutProvider.GetDependency<IInstallationDeviceRepository>() | ||
.Received(0) | ||
.UpsertAsync(Arg.Any<InstallationDeviceEntity>()); | ||
} | ||
|
||
[Theory] | ||
[BitAutoData] | ||
[NotificationCustomize(false)] | ||
public async void PushSyncNotificationAsync_UserIdNullOrganizationIdProvidedClientTypeAll_SentToOrganization( | ||
SutProvider<NotificationHubPushNotificationService> sutProvider, Notification notification) | ||
{ | ||
notification.UserId = null; | ||
notification.ClientType = ClientType.All; | ||
var expectedSyncNotification = ToSyncNotificationPushNotification(notification); | ||
|
||
await sutProvider.Sut.PushSyncNotificationAsync(notification); | ||
|
||
await AssertSendTemplateNotificationAsync(sutProvider, PushType.SyncNotification, expectedSyncNotification, | ||
$"(template:payload && organizationId:{notification.OrganizationId})"); | ||
await sutProvider.GetDependency<IInstallationDeviceRepository>() | ||
.Received(0) | ||
.UpsertAsync(Arg.Any<InstallationDeviceEntity>()); | ||
} | ||
|
||
[Theory] | ||
[BitAutoData(ClientType.Browser)] | ||
[BitAutoData(ClientType.Desktop)] | ||
[BitAutoData(ClientType.Web)] | ||
[BitAutoData(ClientType.Mobile)] | ||
[NotificationCustomize(false)] | ||
public async void PushSyncNotificationAsync_UserIdNullOrganizationIdProvidedClientTypeNotAll_SentToOrganization( | ||
ClientType clientType, SutProvider<NotificationHubPushNotificationService> sutProvider, | ||
Notification notification) | ||
{ | ||
notification.UserId = null; | ||
notification.ClientType = clientType; | ||
|
||
var expectedSyncNotification = ToSyncNotificationPushNotification(notification); | ||
|
||
await sutProvider.Sut.PushSyncNotificationAsync(notification); | ||
|
||
await AssertSendTemplateNotificationAsync(sutProvider, PushType.SyncNotification, expectedSyncNotification, | ||
$"(template:payload && organizationId:{notification.OrganizationId} && clientType:{clientType})"); | ||
await sutProvider.GetDependency<IInstallationDeviceRepository>() | ||
.Received(0) | ||
.UpsertAsync(Arg.Any<InstallationDeviceEntity>()); | ||
} | ||
|
||
private readonly IInstallationDeviceRepository _installationDeviceRepository; | ||
private readonly INotificationHubPool _notificationHubPool; | ||
private readonly IHttpContextAccessor _httpContextAccessor; | ||
private readonly ILogger<NotificationsApiPushNotificationService> _logger; | ||
private static SyncNotificationPushNotification ToSyncNotificationPushNotification(Notification notification) => | ||
new() | ||
{ | ||
Id = notification.Id, | ||
UserId = notification.UserId, | ||
OrganizationId = notification.OrganizationId, | ||
ClientType = notification.ClientType, | ||
RevisionDate = notification.RevisionDate | ||
}; | ||
|
||
public NotificationHubPushNotificationServiceTests() | ||
private static async Task AssertSendTemplateNotificationAsync( | ||
SutProvider<NotificationHubPushNotificationService> sutProvider, PushType type, object payload, string tag) | ||
{ | ||
_installationDeviceRepository = Substitute.For<IInstallationDeviceRepository>(); | ||
_httpContextAccessor = Substitute.For<IHttpContextAccessor>(); | ||
_notificationHubPool = Substitute.For<INotificationHubPool>(); | ||
_logger = Substitute.For<ILogger<NotificationsApiPushNotificationService>>(); | ||
|
||
_sut = new NotificationHubPushNotificationService( | ||
_installationDeviceRepository, | ||
_notificationHubPool, | ||
_httpContextAccessor, | ||
_logger | ||
); | ||
await sutProvider.GetDependency<INotificationHubPool>() | ||
.Received(1) | ||
.AllClients | ||
.Received(1) | ||
.SendTemplateNotificationAsync( | ||
Arg.Is<IDictionary<string, string>>(dictionary => MatchingSendPayload(dictionary, type, payload)), | ||
tag); | ||
} | ||
|
||
// Remove this test when we add actual tests. It only proves that | ||
// we've properly constructed the system under test. | ||
[Fact(Skip = "Needs additional work")] | ||
public void ServiceExists() | ||
private static bool MatchingSendPayload(IDictionary<string, string> dictionary, PushType type, object payload) | ||
{ | ||
Assert.NotNull(_sut); | ||
return dictionary.ContainsKey("type") && dictionary["type"].Equals(((byte)type).ToString()) && | ||
dictionary.ContainsKey("payload") && dictionary["payload"].Equals(JsonSerializer.Serialize(payload)); | ||
} | ||
} |