mirror of
https://github.com/bitwarden/server.git
synced 2025-07-01 16:12:49 -05:00
PM-10600: UT coverage
This commit is contained in:
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
private readonly IInstallationDeviceRepository _installationDeviceRepository;
|
||||
private readonly INotificationHubPool _notificationHubPool;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly ILogger<NotificationsApiPushNotificationService> _logger;
|
||||
|
||||
public NotificationHubPushNotificationServiceTests()
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
[NotificationCustomize]
|
||||
public async void PushSyncNotificationAsync_Global_NotSent(
|
||||
SutProvider<NotificationHubPushNotificationService> sutProvider, Notification notification)
|
||||
{
|
||||
_installationDeviceRepository = Substitute.For<IInstallationDeviceRepository>();
|
||||
_httpContextAccessor = Substitute.For<IHttpContextAccessor>();
|
||||
_notificationHubPool = Substitute.For<INotificationHubPool>();
|
||||
_logger = Substitute.For<ILogger<NotificationsApiPushNotificationService>>();
|
||||
await sutProvider.Sut.PushSyncNotificationAsync(notification);
|
||||
|
||||
_sut = new NotificationHubPushNotificationService(
|
||||
_installationDeviceRepository,
|
||||
_notificationHubPool,
|
||||
_httpContextAccessor,
|
||||
_logger
|
||||
);
|
||||
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>());
|
||||
}
|
||||
|
||||
// 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()
|
||||
[Theory]
|
||||
[BitAutoData(false)]
|
||||
[BitAutoData(true)]
|
||||
[NotificationCustomize(false)]
|
||||
public async void PushSyncNotificationAsync_UserIdProvidedClientTypeAll_SentToUser(
|
||||
bool organizationIdNull, SutProvider<NotificationHubPushNotificationService> sutProvider,
|
||||
Notification notification)
|
||||
{
|
||||
Assert.NotNull(_sut);
|
||||
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 static SyncNotificationPushNotification ToSyncNotificationPushNotification(Notification notification) =>
|
||||
new()
|
||||
{
|
||||
Id = notification.Id,
|
||||
UserId = notification.UserId,
|
||||
OrganizationId = notification.OrganizationId,
|
||||
ClientType = notification.ClientType,
|
||||
RevisionDate = notification.RevisionDate
|
||||
};
|
||||
|
||||
private static async Task AssertSendTemplateNotificationAsync(
|
||||
SutProvider<NotificationHubPushNotificationService> sutProvider, PushType type, object payload, string tag)
|
||||
{
|
||||
await sutProvider.GetDependency<INotificationHubPool>()
|
||||
.Received(1)
|
||||
.AllClients
|
||||
.Received(1)
|
||||
.SendTemplateNotificationAsync(
|
||||
Arg.Is<IDictionary<string, string>>(dictionary => MatchingSendPayload(dictionary, type, payload)),
|
||||
tag);
|
||||
}
|
||||
|
||||
private static bool MatchingSendPayload(IDictionary<string, string> dictionary, PushType type, object payload)
|
||||
{
|
||||
return dictionary.ContainsKey("type") && dictionary["type"].Equals(((byte)type).ToString()) &&
|
||||
dictionary.ContainsKey("payload") && dictionary["payload"].Equals(JsonSerializer.Serialize(payload));
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user