using AutoFixture; using AutoMapper; using Govor.API.Common.SignalR.Helpers; using Govor.API.Hubs; using Govor.Application.Exceptions.FriendsService; using Govor.Application.Interfaces.Friends; using Govor.Application.Interfaces.Infrastructure.Extensions; using Govor.Contracts.DTOs; using Govor.Contracts.Responses.SignalR; using Govor.Domain.Models; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Logging; using Moq; namespace Govor.API.Tests.IntegrationTests.Hubs; [TestFixture] public class FriendsHubTests { private Mock _friendRequestServiceMock = null!; private Mock _currentUserServiceMock = null!; private Mock _clientsMock = null!; private Mock _clientProxyMock = null!; private Mock> _loggerMock = null!; private Mock _mapperMock = null!; private FriendsHub _hub = null!; private Fixture _fixture; private readonly Guid _userId = Guid.NewGuid(); private readonly Guid _targetUserId = Guid.NewGuid(); [SetUp] public void Setup() { _fixture = new Fixture(); _fixture.Behaviors.OfType().ToList().ForEach(b => _fixture.Behaviors.Remove(b)); _fixture.Behaviors.Add(new OmitOnRecursionBehavior()); _friendRequestServiceMock = new Mock(); _currentUserServiceMock = new Mock(); _clientsMock = new Mock(); _clientProxyMock = new Mock(); _loggerMock = new Mock>(); _mapperMock = new Mock(); _currentUserServiceMock.Setup(x => x.GetUserId( It.IsAny(), It.IsAny())) .Returns(_userId); _clientsMock.Setup(c => c.Group(It.IsAny())).Returns(_clientProxyMock.Object); _hub = new FriendsHub( _loggerMock.Object, _friendRequestServiceMock.Object, _currentUserServiceMock.Object, _mapperMock.Object) { Clients = _clientsMock.Object }; } // Tests for SendRequest action [Test] public async Task SendRequest_ShouldReturnCreated_WhenSuccess() { var friendship = _fixture.Build() .With(f => f.Status, FriendshipStatus.Pending) .With(f => f.RequesterId, _userId) .With(f =>f.AddresseeId, _targetUserId) .Create(); var dto = new FriendshipDto() { Id = friendship.Id, Status = FriendshipStatus.Accepted, AddresseeId = friendship.AddresseeId, RequesterId = friendship.RequesterId, }; _mapperMock.Setup(f => f.Map(friendship)) .Returns(dto); _friendRequestServiceMock.Setup(f => f.SendAsync(_userId, _targetUserId)) .ReturnsAsync(friendship); // Act var result = await _hub.SendRequest(_targetUserId); // Assert Assert.That(result, Is.Not.Null); Assert.That(result.Status, Is.EqualTo(HubResultStatus.Created)); _friendRequestServiceMock.Verify(s => s.SendAsync(_userId, _targetUserId), Times.Once); _clientProxyMock.Verify(c => c.SendCoreAsync( "FriendRequestReceived", It.Is(o => o[0]!.Equals(dto)), default), Times.Once); } [Test] public async Task SendRequest_ShouldReturnBadRequest_WhenInvalidOperation() { // Arrange _friendRequestServiceMock .Setup(s => s.SendAsync(_userId, _targetUserId)) .ThrowsAsync(new InvalidOperationException("Invalid")); // Act var result = await _hub.SendRequest(_targetUserId); // Assert Assert.That(result.Status, Is.EqualTo(HubResultStatus.BadRequest)); Assert.That(result.ErrorMessage, Is.EqualTo("Invalid")); } [Test] public async Task SendRequest_ShouldReturnConflict_WhenAlreadySent() { // Arrange _friendRequestServiceMock .Setup(s => s.SendAsync(_userId, _targetUserId)) .ThrowsAsync(new RequestAlreadySentException(_userId, _targetUserId)); // Act var result = await _hub.SendRequest(_targetUserId); // Assert Assert.That(result.Status, Is.EqualTo(HubResultStatus.Conflict)); Assert.That(result.ErrorMessage, Is.EqualTo($"Request was already sent from {_userId} to {_targetUserId}")); } [Test] public async Task SendRequest_ShouldReturnUnauthorized_WhenCurrentUserIsNotAuthenticated() { // Arrange _currentUserServiceMock.Setup(x => x.GetUserId(It.IsAny(), It.IsAny())) .Throws(new UnauthorizedAccessException("userId claim is missing or invalid")); // Act var result = await _hub.SendRequest(_targetUserId); // Assert Assert.That(result.Status, Is.EqualTo(HubResultStatus.Unauthorized)); Assert.That(result.ErrorMessage, Is.EqualTo("userId claim is missing or invalid")); } [Test] public async Task SendRequest_ShouldReturnError_WhenSomeExceptionOccurs() { // Arrange _friendRequestServiceMock .Setup(s => s.SendAsync(_userId, _targetUserId)) .ThrowsAsync(new Exception("error")); // Act var result = await _hub.SendRequest(_targetUserId); // Assert Assert.That(result.Status, Is.EqualTo(HubResultStatus.ServerError)); Assert.That(result.ErrorMessage, Is.EqualTo("Unexpected error! Please try later!")); } // Test for AcceptRequest action [Test] public async Task AcceptRequest_ShouldReturnOk_WhenSuccess() { // Arrange var friendship = _fixture.Build() .With(f => f.Status, FriendshipStatus.Pending) .Create(); var dto = new FriendshipDto() { Id = friendship.Id, Status = FriendshipStatus.Accepted, AddresseeId = friendship.AddresseeId, RequesterId = friendship.RequesterId }; _mapperMock.Setup(f => f.Map(friendship)) .Returns(dto); _friendRequestServiceMock.Setup(f => f.AcceptAsync(friendship.Id, _userId)) .ReturnsAsync(friendship); // Act var result = await _hub.AcceptRequest(friendship.Id); // Assert Assert.That(result.Status, Is.EqualTo(HubResultStatus.Success)); _friendRequestServiceMock.Verify(s => s.AcceptAsync(friendship.Id, _userId), Times.Once); _clientProxyMock.Verify(c => c.SendCoreAsync( "FriendRequestAccepted", It.Is(o => o.Length == 1 && o[0] == dto), default), Times.Once); } [Test] public async Task AcceptRequest_ShouldReturnBadRequest_InvalidOperation() { // Arrange var friendshipId = Guid.NewGuid(); _friendRequestServiceMock .Setup(s => s.AcceptAsync(friendshipId, _userId)) .ThrowsAsync(new InvalidOperationException("Invalid")); // Act var result = await _hub.AcceptRequest(friendshipId); // Assert Assert.That(result.Status, Is.EqualTo(HubResultStatus.BadRequest)); Assert.That(result.ErrorMessage, Is.EqualTo("Invalid")); } [Test] public async Task AcceptRequest_ShouldReturnUnauthorized_UnauthorizedAccess() { // Arrange var friendshipId = Guid.NewGuid(); _friendRequestServiceMock .Setup(s => s.AcceptAsync(friendshipId, _userId)) .ThrowsAsync(new UnauthorizedAccessException("userId claim is missing or invalid")); // Act var result = await _hub.AcceptRequest(friendshipId); // Assert Assert.That(result.Status, Is.EqualTo(HubResultStatus.Unauthorized)); Assert.That(result.ErrorMessage, Is.EqualTo("userId claim is missing or invalid")); } [Test] public async Task AcceptRequest_ShouldReturnError_WhenSomeExceptionOccurs() { // Arrange var friendshipId = Guid.NewGuid(); _friendRequestServiceMock .Setup(s => s.AcceptAsync(friendshipId, _userId)) .ThrowsAsync(new Exception("error")); // Act var result = await _hub.AcceptRequest(friendshipId); // Assert Assert.That(result.Status, Is.EqualTo(HubResultStatus.ServerError)); Assert.That(result.ErrorMessage, Is.EqualTo("Unexpected error! Please try later!")); } // Test for RejectRequest action [Test] public async Task RejectRequest_ShouldReturnOk_WhenSuccess() { // Arrange var friendship = _fixture.Build() .With(f => f.Status, FriendshipStatus.Pending) .Create(); var dto = new FriendshipDto() { Id = friendship.Id, Status = FriendshipStatus.Accepted, AddresseeId = friendship.AddresseeId, RequesterId = friendship.RequesterId }; _mapperMock.Setup(f => f.Map(friendship)) .Returns(dto); _friendRequestServiceMock.Setup(f => f.RejectAsync(friendship.Id, _userId)) .ReturnsAsync(friendship); // Act var result = await _hub.RejectRequest(friendship.Id); // Assert Assert.That(result.Status, Is.EqualTo(HubResultStatus.Success)); _friendRequestServiceMock.Verify(s => s.RejectAsync(friendship.Id, _userId), Times.Once); _clientProxyMock.Verify(c => c.SendCoreAsync( "FriendRequestRejected", It.Is(o => o[0]!.Equals(dto)), default), Times.Once); } [Test] public async Task RejectRequest_ShouldReturnBadRequest_InvalidOperation() { // Arrange var friendshipId = Guid.NewGuid(); _friendRequestServiceMock .Setup(s => s.RejectAsync(friendshipId, _userId)) .ThrowsAsync(new InvalidOperationException("Invalid")); // Act var result = await _hub.RejectRequest(friendshipId); // Assert Assert.That(result.Status, Is.EqualTo(HubResultStatus.BadRequest)); Assert.That(result.ErrorMessage, Is.EqualTo("Invalid")); } [Test] public async Task RejectRequest_ShouldReturnUnauthorized_UnauthorizedAccess() { // Arrange var friendshipId = Guid.NewGuid(); _friendRequestServiceMock .Setup(s => s.RejectAsync(friendshipId, _userId)) .ThrowsAsync(new UnauthorizedAccessException("userId claim is missing or invalid")); // Act var result = await _hub.RejectRequest(friendshipId); // Assert Assert.That(result.Status, Is.EqualTo(HubResultStatus.Unauthorized)); Assert.That(result.ErrorMessage, Is.EqualTo("userId claim is missing or invalid")); } [Test] public async Task RejectRequest_ShouldReturnError_WhenSomeExceptionOccurs() { // Arrange var friendshipId = Guid.NewGuid(); _friendRequestServiceMock .Setup(s => s.RejectAsync(friendshipId, _userId)) .ThrowsAsync(new Exception("error")); // Act var result = await _hub.RejectRequest(friendshipId); // Assert Assert.That(result.Status, Is.EqualTo(HubResultStatus.ServerError)); Assert.That(result.ErrorMessage, Is.EqualTo("Unexpected error! Please try later!")); } [TearDown] public void TearDown() { _hub?.Dispose(); } }