mirror of
https://github.com/Govor-team/Govor.git
synced 2026-07-21 19:54:55 +00:00
test
This commit is contained in:
@@ -2,6 +2,8 @@ using AutoFixture;
|
|||||||
using Govor.API.Common.SignalR.Helpers;
|
using Govor.API.Common.SignalR.Helpers;
|
||||||
using Govor.API.Hubs;
|
using Govor.API.Hubs;
|
||||||
using Govor.Application.Interfaces.UserOnlineStatus;
|
using Govor.Application.Interfaces.UserOnlineStatus;
|
||||||
|
using Govor.Core.Repositories.Users;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Moq;
|
using Moq;
|
||||||
|
|
||||||
@@ -16,11 +18,89 @@ public class PresenceHubTests
|
|||||||
private Mock<IUserNotificationScopeService> _mockUserNotification;
|
private Mock<IUserNotificationScopeService> _mockUserNotification;
|
||||||
private Mock<IOnlineUserStore> _mockOnlineUserStore;
|
private Mock<IOnlineUserStore> _mockOnlineUserStore;
|
||||||
private Mock<IHubUserAccessor> _mockHubUserAccessor;
|
private Mock<IHubUserAccessor> _mockHubUserAccessor;
|
||||||
|
private Mock<IUsersRepository> _mockUserRepository;
|
||||||
|
private Mock<IHubCallerClients> _clientsMock = null!;
|
||||||
|
private Mock<IClientProxy> _clientProxyMock = null!;
|
||||||
|
private Mock<HubCallerContext> _mockContext = null!;
|
||||||
|
private Mock<IGroupManager> _groupManagerMock = null!;
|
||||||
private Fixture _fixture;
|
private Fixture _fixture;
|
||||||
|
private PresenceHub _hub;
|
||||||
|
private Guid _userId;
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void SetUp()
|
public void SetUp()
|
||||||
{
|
{
|
||||||
|
_fixture = new Fixture();
|
||||||
|
_fixture.Behaviors.OfType<ThrowingRecursionBehavior>().ToList().ForEach(b => _fixture.Behaviors.Remove(b));
|
||||||
|
_fixture.Behaviors.Add(new OmitOnRecursionBehavior());
|
||||||
|
|
||||||
|
_mockLogger = new Mock<ILogger<PresenceHub>>();
|
||||||
|
_mockUserNotification = new Mock<IUserNotificationScopeService>();
|
||||||
|
_mockOnlineUserStore = new Mock<IOnlineUserStore>();
|
||||||
|
_mockHubUserAccessor = new Mock<IHubUserAccessor>();
|
||||||
|
_mockUserRepository = new Mock<IUsersRepository>();
|
||||||
|
|
||||||
|
_clientsMock = new Mock<IHubCallerClients>();
|
||||||
|
_clientProxyMock = new Mock<IClientProxy>();
|
||||||
|
|
||||||
|
_userId = Guid.NewGuid();
|
||||||
|
_mockHubUserAccessor.Setup(h => h.GetUserId(
|
||||||
|
It.IsAny<HubCallerContext>(),
|
||||||
|
It.IsAny<bool>()))
|
||||||
|
.Returns(_userId);
|
||||||
|
|
||||||
|
|
||||||
|
_clientsMock.Setup(c => c.Group(It.IsAny<string>())).Returns(_clientProxyMock.Object);
|
||||||
|
_mockContext = new Mock<HubCallerContext>();
|
||||||
|
_mockContext.Setup(c => c.ConnectionId).Returns("test-connection");
|
||||||
|
|
||||||
|
_groupManagerMock = new Mock<IGroupManager>();
|
||||||
|
|
||||||
|
_groupManagerMock.Setup(g => g.AddToGroupAsync(It.IsAny<string>(), It.IsAny<string>(), default))
|
||||||
|
.Returns(Task.CompletedTask);
|
||||||
|
|
||||||
|
_hub = new PresenceHub(
|
||||||
|
_mockLogger.Object,
|
||||||
|
_mockUserNotification.Object,
|
||||||
|
_mockOnlineUserStore.Object,
|
||||||
|
_mockHubUserAccessor.Object,
|
||||||
|
_mockUserRepository.Object)
|
||||||
|
{
|
||||||
|
Clients = _clientsMock.Object,
|
||||||
|
Context = _mockContext.Object,
|
||||||
|
Groups = _groupManagerMock.Object,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests for OnConnectedAsync action
|
||||||
|
[Test]
|
||||||
|
public async Task OnConnectedAsync_SetsUserOnlineAndNotifiesFriends()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_mockUserRepository.Setup(f => f.ExistsByIdAsync(_userId))
|
||||||
|
.ReturnsAsync(true);
|
||||||
|
|
||||||
|
var friendsIds = _fixture.CreateMany<Guid>().ToList();
|
||||||
|
|
||||||
|
_mockUserNotification.Setup(n => n.GetNotifiedUsers(_userId))
|
||||||
|
.ReturnsAsync(friendsIds);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await _hub.OnConnectedAsync();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
_mockOnlineUserStore.Verify(store => store.SetOnlineUser(_userId), Times.Once);
|
||||||
|
|
||||||
|
_clientsMock.Verify(c => c.Group(It.IsAny<string>()), Times.Exactly(friendsIds.Count));
|
||||||
|
|
||||||
|
foreach (var friendId in friendsIds)
|
||||||
|
{
|
||||||
|
_clientProxyMock.Verify(proxy =>
|
||||||
|
proxy.SendCoreAsync("UserOnline",
|
||||||
|
It.Is<object[]>(args => args.Length == 1 && (Guid)args[0] == _userId),
|
||||||
|
It.IsAny<CancellationToken>()),
|
||||||
|
Times.Exactly(friendsIds.Count));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -49,7 +49,6 @@ public class FriendsHub : Hub
|
|||||||
var userId = _userAccessor.GetUserId(Context, true);
|
var userId = _userAccessor.GetUserId(Context, true);
|
||||||
if (userId != Guid.Empty)
|
if (userId != Guid.Empty)
|
||||||
{
|
{
|
||||||
// Remove user from their own group
|
|
||||||
await Groups.RemoveFromGroupAsync(Context.ConnectionId, userId.ToString());
|
await Groups.RemoveFromGroupAsync(Context.ConnectionId, userId.ToString());
|
||||||
_logger.LogInformation(
|
_logger.LogInformation(
|
||||||
"User {UserId} disconnected with ConnectionId {ConnectionId} and removed from their group", userId,
|
"User {UserId} disconnected with ConnectionId {ConnectionId} and removed from their group", userId,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Govor.API.Common.SignalR.Helpers;
|
using Govor.API.Common.SignalR.Helpers;
|
||||||
using Govor.Application.Interfaces.UserOnlineStatus;
|
using Govor.Application.Interfaces.UserOnlineStatus;
|
||||||
|
using Govor.Core.Repositories.Users;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Microsoft.AspNetCore.SignalR;
|
using Microsoft.AspNetCore.SignalR;
|
||||||
@@ -11,18 +12,21 @@ namespace Govor.API.Hubs;
|
|||||||
public class PresenceHub : Hub
|
public class PresenceHub : Hub
|
||||||
{
|
{
|
||||||
private readonly ILogger<PresenceHub> _logger;
|
private readonly ILogger<PresenceHub> _logger;
|
||||||
private readonly IUserNotificationScopeService _notificationScopeService;
|
private readonly IUserNotificationScopeService _scopeService;
|
||||||
private readonly IOnlineUserStore _onlineUserStore;
|
private readonly IOnlineUserStore _onlineUserStore;
|
||||||
private readonly IHubUserAccessor _userAccessor;
|
private readonly IHubUserAccessor _userAccessor;
|
||||||
|
private readonly IUsersRepository _users;
|
||||||
|
|
||||||
public PresenceHub(
|
public PresenceHub(
|
||||||
ILogger<PresenceHub> logger,
|
ILogger<PresenceHub> logger,
|
||||||
IUserNotificationScopeService notificationScopeService,
|
IUserNotificationScopeService scopeService,
|
||||||
IOnlineUserStore onlineUserStore,
|
IOnlineUserStore onlineUserStore,
|
||||||
IHubUserAccessor userAccessor)
|
IHubUserAccessor userAccessor,
|
||||||
|
IUsersRepository users)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_notificationScopeService = notificationScopeService;
|
_users = users;
|
||||||
|
_scopeService = scopeService;
|
||||||
_onlineUserStore = onlineUserStore;
|
_onlineUserStore = onlineUserStore;
|
||||||
_userAccessor = userAccessor;
|
_userAccessor = userAccessor;
|
||||||
}
|
}
|
||||||
@@ -30,9 +34,9 @@ public class PresenceHub : Hub
|
|||||||
public override async Task OnConnectedAsync()
|
public override async Task OnConnectedAsync()
|
||||||
{
|
{
|
||||||
var userId = _userAccessor.GetUserId(Context);
|
var userId = _userAccessor.GetUserId(Context);
|
||||||
if (userId == Guid.Empty)
|
if (userId == Guid.Empty || await _users.ExistsByIdAsync(userId) == false)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("User connected with invalid UserID claim.");
|
_logger.LogWarning("User connected with invalid UserId claim.");
|
||||||
Context.Abort();
|
Context.Abort();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -40,7 +44,7 @@ public class PresenceHub : Hub
|
|||||||
_onlineUserStore.SetOnlineUser(userId);
|
_onlineUserStore.SetOnlineUser(userId);
|
||||||
await Groups.AddToGroupAsync(Context.ConnectionId, userId.ToString());
|
await Groups.AddToGroupAsync(Context.ConnectionId, userId.ToString());
|
||||||
|
|
||||||
var friends = await _notificationScopeService.GetNotifiedUsers(userId);
|
var friends = await _scopeService.GetNotifiedUsers(userId);
|
||||||
|
|
||||||
foreach (var recipient in friends)
|
foreach (var recipient in friends)
|
||||||
{
|
{
|
||||||
@@ -51,14 +55,33 @@ public class PresenceHub : Hub
|
|||||||
await base.OnConnectedAsync();
|
await base.OnConnectedAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task OnDisconnectedAsync(Exception? exception)
|
public override async Task OnDisconnectedAsync(Exception exception)
|
||||||
{
|
{
|
||||||
var userId = _userAccessor.GetUserId(Context, true);
|
var userId = _userAccessor.GetUserId(Context, true);
|
||||||
if (userId == Guid.Empty) return;
|
|
||||||
|
if (userId != Guid.Empty)
|
||||||
|
{
|
||||||
|
await Groups.RemoveFromGroupAsync(Context.ConnectionId, userId.ToString());
|
||||||
|
_logger.LogInformation(
|
||||||
|
"User {UserId} disconnected with ConnectionId {ConnectionId} and removed from their group", userId,
|
||||||
|
Context.ConnectionId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogInformation(
|
||||||
|
"User disconnected with no exception and invalid UserID claim. ConnectionId: {ConnectionId}",
|
||||||
|
Context.ConnectionId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_onlineUserStore.SetOfflineUser(userId);
|
_onlineUserStore.SetOfflineUser(userId);
|
||||||
|
|
||||||
var friends = await _notificationScopeService.GetNotifiedUsers(userId);
|
// Updating was online
|
||||||
|
var user = await _users.FindByIdAsync(userId);
|
||||||
|
user.WasOnline = DateTime.UtcNow;
|
||||||
|
await _users.UpdateAsync(user);
|
||||||
|
|
||||||
|
var friends = await _scopeService.GetNotifiedUsers(userId);
|
||||||
|
|
||||||
foreach (var recipient in friends)
|
foreach (var recipient in friends)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user