mirror of
https://github.com/bitwarden/server.git
synced 2024-11-21 12:05:42 +01:00
PM-10600: Unit test coverage for RelayPushNotificationService
This commit is contained in:
parent
71603055ff
commit
98fbe1f110
@ -242,6 +242,11 @@ public class RelayPushNotificationService : BaseIdentityClientService, IPushNoti
|
||||
await SendAsync(HttpMethod.Post, "push/send", request);
|
||||
}
|
||||
|
||||
internal virtual async Task SendAsync(HttpMethod method, string path, object payload)
|
||||
{
|
||||
await base.SendAsync(method, path, payload);
|
||||
}
|
||||
|
||||
private async Task AddCurrentContextAsync(PushSendRequestModel request, bool addIdentifier)
|
||||
{
|
||||
var currentContext =
|
||||
|
@ -20,7 +20,7 @@ using Xunit;
|
||||
|
||||
namespace Bit.Core.Test.Services;
|
||||
|
||||
[SutProviderCustomize]
|
||||
[SutProviderCustomize(false)]
|
||||
[HttpClientCustomize]
|
||||
public class NotificationsApiPushNotificationServiceTests
|
||||
{
|
||||
@ -32,9 +32,10 @@ public class NotificationsApiPushNotificationServiceTests
|
||||
MockedHttpMessageHandler mockedHttpMessageHandler)
|
||||
{
|
||||
globalSettings.SelfHosted = true;
|
||||
globalSettings.BaseServiceUri = new GlobalSettings.BaseServiceUriSettings(globalSettings);
|
||||
globalSettings.ProjectName = "Notifications";
|
||||
globalSettings.InternalIdentityKey = "internal-identity-key";
|
||||
sutProvider.SetDependency(typeof(GlobalSettings), globalSettings)
|
||||
.Create();
|
||||
|
||||
var tokenResponse = mockedHttpMessageHandler
|
||||
.When(request =>
|
||||
@ -59,12 +60,6 @@ public class NotificationsApiPushNotificationServiceTests
|
||||
request.Headers.Authorization?.ToString() == "Bearer token")
|
||||
.RespondWith(HttpStatusCode.OK);
|
||||
|
||||
sutProvider.Reset();
|
||||
sutProvider.SetDependency(typeof(GlobalSettings), globalSettings)
|
||||
.Create();
|
||||
|
||||
// var sut = new NotificationsApiPushNotificationService(httpFactory, globalSettings, httpContextAccessor, logger);
|
||||
|
||||
await sutProvider.Sut.SendAsync(HttpMethod.Post, "send", "payload");
|
||||
|
||||
Assert.Equal(1, tokenResponse.NumberOfResponses);
|
||||
@ -79,6 +74,11 @@ public class NotificationsApiPushNotificationServiceTests
|
||||
SutProvider<NotificationsApiPushNotificationService> sutProvider, Notification notification,
|
||||
Guid deviceIdentifier, ICurrentContext currentContext, MockedHttpMessageHandler mockedHttpMessageHandler)
|
||||
{
|
||||
sutProvider.Create();
|
||||
currentContext.DeviceIdentifier.Returns(deviceIdentifier.ToString());
|
||||
sutProvider.GetDependency<IHttpContextAccessor>().HttpContext!.RequestServices
|
||||
.GetService(Arg.Any<Type>()).Returns(currentContext);
|
||||
|
||||
var tokenResponse = mockedHttpMessageHandler
|
||||
.When(request =>
|
||||
request.Method == HttpMethod.Post && request.RequestUri!.ToString().EndsWith("/connect/token"))
|
||||
@ -98,10 +98,6 @@ public class NotificationsApiPushNotificationServiceTests
|
||||
})
|
||||
.RespondWith(HttpStatusCode.OK);
|
||||
|
||||
currentContext.DeviceIdentifier.Returns(deviceIdentifier.ToString());
|
||||
sutProvider.GetDependency<IHttpContextAccessor>().HttpContext!.RequestServices
|
||||
.GetService(Arg.Any<Type>()).Returns(currentContext);
|
||||
|
||||
await sutProvider.Sut.PushSyncNotificationAsync(notification);
|
||||
|
||||
Assert.Equal(1, tokenResponse.NumberOfResponses);
|
||||
|
@ -1,45 +1,307 @@
|
||||
using Bit.Core.Repositories;
|
||||
#nullable enable
|
||||
using System.Net;
|
||||
using System.Net.Http.Json;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models;
|
||||
using Bit.Core.Models.Api;
|
||||
using Bit.Core.NotificationCenter.Entities;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Settings;
|
||||
using Bit.Core.Test.AutoFixture;
|
||||
using Bit.Core.Test.AutoFixture.CurrentContextFixtures;
|
||||
using Bit.Core.Test.NotificationCenter.AutoFixture;
|
||||
using Bit.Test.Common.AutoFixture;
|
||||
using Bit.Test.Common.AutoFixture.Attributes;
|
||||
using Bit.Test.Common.MockedHttpClient;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.AspNetCore.WebUtilities;
|
||||
using NSubstitute;
|
||||
using Xunit;
|
||||
|
||||
namespace Bit.Core.Test.Services;
|
||||
|
||||
[SutProviderCustomize(false)]
|
||||
[HttpClientCustomize]
|
||||
public class RelayPushNotificationServiceTests
|
||||
{
|
||||
private readonly RelayPushNotificationService _sut;
|
||||
|
||||
private readonly IHttpClientFactory _httpFactory;
|
||||
private readonly IDeviceRepository _deviceRepository;
|
||||
private readonly GlobalSettings _globalSettings;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly ILogger<RelayPushNotificationService> _logger;
|
||||
|
||||
public RelayPushNotificationServiceTests()
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
[GlobalSettingsCustomize]
|
||||
public async void Constructor_DefaultGlobalSettings_CorrectHttpRequests(
|
||||
SutProvider<RelayPushNotificationService> sutProvider, GlobalSettings globalSettings,
|
||||
MockedHttpMessageHandler mockedHttpMessageHandler, Guid installationId)
|
||||
{
|
||||
_httpFactory = Substitute.For<IHttpClientFactory>();
|
||||
_deviceRepository = Substitute.For<IDeviceRepository>();
|
||||
_globalSettings = new GlobalSettings();
|
||||
_httpContextAccessor = Substitute.For<IHttpContextAccessor>();
|
||||
_logger = Substitute.For<ILogger<RelayPushNotificationService>>();
|
||||
ConfigureSut(sutProvider, globalSettings, installationId);
|
||||
|
||||
_sut = new RelayPushNotificationService(
|
||||
_httpFactory,
|
||||
_deviceRepository,
|
||||
_globalSettings,
|
||||
_httpContextAccessor,
|
||||
_logger
|
||||
);
|
||||
}
|
||||
|
||||
// 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()
|
||||
var tokenResponse = mockedHttpMessageHandler
|
||||
.When(request =>
|
||||
{
|
||||
Assert.NotNull(_sut);
|
||||
if (request.Method != HttpMethod.Post ||
|
||||
!request.RequestUri!.Equals(new Uri("http://installation-identity-test.localhost/connect/token")))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Assert.NotNull(request.Content);
|
||||
Assert.NotNull(request.Content.Headers.ContentType);
|
||||
Assert.Equal("application/x-www-form-urlencoded", request.Content.Headers.ContentType.MediaType);
|
||||
|
||||
var formReader = new FormReader(request.Content.ReadAsStream()).ReadForm();
|
||||
|
||||
Assert.Contains("scope", formReader);
|
||||
Assert.Equal("api.push", formReader["scope"]);
|
||||
Assert.Contains("client_id", formReader);
|
||||
Assert.Equal($"installation.{globalSettings.Installation.Id}", formReader["client_id"]);
|
||||
Assert.Contains("client_secret", formReader);
|
||||
Assert.Equal("installation-key", formReader["client_secret"]);
|
||||
|
||||
return true;
|
||||
})
|
||||
.RespondWith(HttpStatusCode.OK, new StringContent("{\"access_token\":\"token\"}"));
|
||||
var sendResponse = mockedHttpMessageHandler
|
||||
.When(request =>
|
||||
{
|
||||
if (request.Method != HttpMethod.Post ||
|
||||
!request.RequestUri!.Equals(new Uri("http://push-relay-test.localhost/push/send")))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Assert.Equal("Bearer token", request.Headers.Authorization?.ToString());
|
||||
|
||||
return true;
|
||||
})
|
||||
.RespondWith(HttpStatusCode.OK);
|
||||
|
||||
await sutProvider.Sut.SendAsync(HttpMethod.Post, "push/send", "payload");
|
||||
|
||||
Assert.Equal(1, tokenResponse.NumberOfResponses);
|
||||
Assert.Equal(1, sendResponse.NumberOfResponses);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
[NotificationCustomize]
|
||||
[CurrentContextCustomize]
|
||||
[GlobalSettingsCustomize]
|
||||
public async void PushSyncNotificationAsync_GlobalNotification_NothingSent(
|
||||
SutProvider<RelayPushNotificationService> sutProvider, Notification notification,
|
||||
MockedHttpMessageHandler mockedHttpMessageHandler, GlobalSettings globalSettings, Guid installationId)
|
||||
{
|
||||
ConfigureSut(sutProvider, globalSettings, installationId);
|
||||
|
||||
var response = mockedHttpMessageHandler
|
||||
.When(request => true)
|
||||
.RespondWith(HttpStatusCode.OK);
|
||||
|
||||
await sutProvider.Sut.PushSyncNotificationAsync(notification);
|
||||
|
||||
Assert.Equal(0, response.NumberOfResponses);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(true, true, true)]
|
||||
[BitAutoData(true, true, false)]
|
||||
[BitAutoData(true, false, true)]
|
||||
[BitAutoData(true, false, false)]
|
||||
[BitAutoData(false, true, true)]
|
||||
[BitAutoData(false, true, false)]
|
||||
[BitAutoData(false, false, true)]
|
||||
[BitAutoData(false, false, false)]
|
||||
[NotificationCustomize(false)]
|
||||
[CurrentContextCustomize]
|
||||
[GlobalSettingsCustomize]
|
||||
public async void PushSyncNotificationAsync_NotificationUserIdSet_SentToUser(bool withOrganizationId,
|
||||
bool withDeviceIdentifier, bool deviceFound, Device device,
|
||||
SutProvider<RelayPushNotificationService> sutProvider, Notification notification, Guid deviceIdentifier,
|
||||
ICurrentContext currentContext, MockedHttpMessageHandler mockedHttpMessageHandler,
|
||||
GlobalSettings globalSettings, Guid installationId)
|
||||
{
|
||||
if (!withOrganizationId)
|
||||
{
|
||||
notification.OrganizationId = null;
|
||||
}
|
||||
|
||||
ConfigureSut(sutProvider, globalSettings, installationId);
|
||||
|
||||
if (withDeviceIdentifier)
|
||||
{
|
||||
currentContext.DeviceIdentifier.Returns(deviceIdentifier.ToString());
|
||||
if (deviceFound)
|
||||
{
|
||||
sutProvider.GetDependency<IDeviceRepository>().GetByIdentifierAsync(deviceIdentifier.ToString())
|
||||
.Returns(device);
|
||||
}
|
||||
}
|
||||
|
||||
sutProvider.GetDependency<IHttpContextAccessor>().HttpContext!.RequestServices
|
||||
.GetService(Arg.Any<Type>()).Returns(currentContext);
|
||||
|
||||
var tokenResponse = mockedHttpMessageHandler
|
||||
.When(request =>
|
||||
request.Method == HttpMethod.Post && request.RequestUri!.ToString().EndsWith("/connect/token"))
|
||||
.RespondWith(HttpStatusCode.OK, new StringContent("{\"access_token\":\"token\"}"));
|
||||
var sendResponse = mockedHttpMessageHandler
|
||||
.When(request =>
|
||||
{
|
||||
if (request.Method != HttpMethod.Post || !request.RequestUri!.ToString().EndsWith("/push/send"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Assert.NotNull(request.Content);
|
||||
var jsonContent = Assert.IsType<JsonContent>(request.Content);
|
||||
Assert.NotNull(jsonContent.Value);
|
||||
|
||||
var pushSendRequest = Assert.IsType<PushSendRequestModel>(jsonContent.Value);
|
||||
AssertRequest(pushSendRequest,
|
||||
new PushSendRequestModel
|
||||
{
|
||||
Type = PushType.SyncNotification,
|
||||
Payload = new SyncNotificationPushNotification
|
||||
{
|
||||
Id = notification.Id,
|
||||
UserId = notification.UserId,
|
||||
OrganizationId = notification.OrganizationId,
|
||||
ClientType = notification.ClientType,
|
||||
RevisionDate = notification.RevisionDate
|
||||
},
|
||||
UserId = notification.UserId!.ToString(),
|
||||
OrganizationId = null,
|
||||
DeviceId = withDeviceIdentifier && deviceFound ? device.Id.ToString() : null,
|
||||
Identifier = withDeviceIdentifier ? deviceIdentifier.ToString() : null,
|
||||
ClientType = notification.ClientType
|
||||
},
|
||||
new SyncNotificationEquals());
|
||||
return true;
|
||||
})
|
||||
.RespondWith(HttpStatusCode.OK);
|
||||
|
||||
await sutProvider.Sut.PushSyncNotificationAsync(notification);
|
||||
|
||||
Assert.Equal(1, tokenResponse.NumberOfResponses);
|
||||
Assert.Equal(1, sendResponse.NumberOfResponses);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(true, true)]
|
||||
[BitAutoData(true, false)]
|
||||
[BitAutoData(false, true)]
|
||||
[BitAutoData(false, false)]
|
||||
[NotificationCustomize(false)]
|
||||
[CurrentContextCustomize]
|
||||
[GlobalSettingsCustomize]
|
||||
public async void PushSyncNotificationAsync_NotificationOrganizationIdSet_SentToOrganization(
|
||||
bool withDeviceIdentifier, bool deviceFound, Device device,
|
||||
SutProvider<RelayPushNotificationService> sutProvider, Notification notification, Guid deviceIdentifier,
|
||||
ICurrentContext currentContext, MockedHttpMessageHandler mockedHttpMessageHandler,
|
||||
GlobalSettings globalSettings, Guid installationId)
|
||||
{
|
||||
notification.UserId = null;
|
||||
|
||||
ConfigureSut(sutProvider, globalSettings, installationId);
|
||||
|
||||
if (withDeviceIdentifier)
|
||||
{
|
||||
currentContext.DeviceIdentifier.Returns(deviceIdentifier.ToString());
|
||||
if (deviceFound)
|
||||
{
|
||||
sutProvider.GetDependency<IDeviceRepository>().GetByIdentifierAsync(deviceIdentifier.ToString())
|
||||
.Returns(device);
|
||||
}
|
||||
}
|
||||
|
||||
sutProvider.GetDependency<IHttpContextAccessor>().HttpContext!.RequestServices
|
||||
.GetService(Arg.Any<Type>()).Returns(currentContext);
|
||||
|
||||
var tokenResponse = mockedHttpMessageHandler
|
||||
.When(request =>
|
||||
request.Method == HttpMethod.Post && request.RequestUri!.ToString().EndsWith("/connect/token"))
|
||||
.RespondWith(HttpStatusCode.OK, new StringContent("{\"access_token\":\"token\"}"));
|
||||
var sendResponse = mockedHttpMessageHandler
|
||||
.When(request =>
|
||||
{
|
||||
if (request.Method != HttpMethod.Post || !request.RequestUri!.ToString().EndsWith("/push/send"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Assert.NotNull(request.Content);
|
||||
var jsonContent = Assert.IsType<JsonContent>(request.Content);
|
||||
Assert.NotNull(jsonContent.Value);
|
||||
|
||||
var pushSendRequest = Assert.IsType<PushSendRequestModel>(jsonContent.Value);
|
||||
AssertRequest(pushSendRequest,
|
||||
new PushSendRequestModel
|
||||
{
|
||||
Type = PushType.SyncNotification,
|
||||
Payload = new SyncNotificationPushNotification
|
||||
{
|
||||
Id = notification.Id,
|
||||
UserId = notification.UserId,
|
||||
OrganizationId = notification.OrganizationId,
|
||||
ClientType = notification.ClientType,
|
||||
RevisionDate = notification.RevisionDate
|
||||
},
|
||||
UserId = null,
|
||||
OrganizationId = notification.OrganizationId!.ToString(),
|
||||
DeviceId = withDeviceIdentifier && deviceFound ? device.Id.ToString() : null,
|
||||
Identifier = withDeviceIdentifier ? deviceIdentifier.ToString() : null,
|
||||
ClientType = notification.ClientType
|
||||
},
|
||||
new SyncNotificationEquals());
|
||||
return true;
|
||||
})
|
||||
.RespondWith(HttpStatusCode.OK);
|
||||
|
||||
await sutProvider.Sut.PushSyncNotificationAsync(notification);
|
||||
|
||||
Assert.Equal(1, tokenResponse.NumberOfResponses);
|
||||
Assert.Equal(1, sendResponse.NumberOfResponses);
|
||||
}
|
||||
|
||||
private static void AssertRequest<T>(PushSendRequestModel request, PushSendRequestModel expectedRequest,
|
||||
IEqualityComparer<T> expectedPayloadEquatable)
|
||||
{
|
||||
Assert.Equal(expectedRequest.Type, request.Type);
|
||||
Assert.Equal(expectedRequest.UserId, request.UserId);
|
||||
Assert.Equal(expectedRequest.OrganizationId, request.OrganizationId);
|
||||
Assert.Equal(expectedRequest.DeviceId, request.DeviceId);
|
||||
Assert.Equal(expectedRequest.Identifier, request.Identifier);
|
||||
Assert.Equal(expectedRequest.ClientType, request.ClientType);
|
||||
Assert.Equal((T)expectedRequest.Payload, (T)request.Payload, expectedPayloadEquatable);
|
||||
}
|
||||
|
||||
private class SyncNotificationEquals : IEqualityComparer<SyncNotificationPushNotification>
|
||||
{
|
||||
public bool Equals(SyncNotificationPushNotification? x, SyncNotificationPushNotification? y)
|
||||
{
|
||||
if (ReferenceEquals(x, y)) return true;
|
||||
if (x is null) return false;
|
||||
if (y is null) return false;
|
||||
if (x.GetType() != y.GetType()) return false;
|
||||
return x.Id.Equals(y.Id) && Nullable.Equals(x.UserId, y.UserId) &&
|
||||
Nullable.Equals(x.OrganizationId, y.OrganizationId) && x.ClientType == y.ClientType &&
|
||||
x.RevisionDate.Equals(y.RevisionDate);
|
||||
}
|
||||
|
||||
public int GetHashCode(SyncNotificationPushNotification obj)
|
||||
{
|
||||
return HashCode.Combine(obj.Id, obj.UserId, obj.OrganizationId, (int)obj.ClientType, obj.RevisionDate);
|
||||
}
|
||||
}
|
||||
|
||||
private void ConfigureSut(SutProvider<RelayPushNotificationService> sutProvider, GlobalSettings globalSettings,
|
||||
Guid installationId)
|
||||
{
|
||||
globalSettings.PushRelayBaseUri = "http://push-relay-test.localhost";
|
||||
globalSettings.Installation.IdentityUri = "http://installation-identity-test.localhost";
|
||||
globalSettings.Installation.Id = installationId;
|
||||
globalSettings.Installation.Key = "installation-key";
|
||||
sutProvider.SetDependency(typeof(GlobalSettings), globalSettings)
|
||||
.Create();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user