mirror of
https://github.com/Govor-team/Govor.git
synced 2026-07-21 11:44:56 +00:00
was added firebase nitifying
This commit is contained in:
@@ -1,51 +1,103 @@
|
||||
using AutoFixture;
|
||||
using Govor.Application.Interfaces.Authentication;
|
||||
using Govor.Application.Services.Authentication;
|
||||
|
||||
namespace Govor.Application.Tests.Services.Authentication;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
[TestFixture]
|
||||
public class JwtTokenHasherTests
|
||||
{
|
||||
private IJwtTokenHasher _jwtTokenHasher;
|
||||
private Fixture _fixture;
|
||||
|
||||
private const string TestSecret = "SuperSecretPepper123!";
|
||||
|
||||
[SetUp]
|
||||
public void StarUp()
|
||||
public void StartUp()
|
||||
{
|
||||
_fixture = new Fixture();
|
||||
//_jwtTokenHasher = new JwtTokenHasher();
|
||||
|
||||
var config = new ConfigurationBuilder()
|
||||
.AddInMemoryCollection(new Dictionary<string, string?>
|
||||
{
|
||||
{ "EncryptionOption:Secret", TestSecret }
|
||||
})
|
||||
.Build();
|
||||
|
||||
_jwtTokenHasher = new JwtTokenHasher(config);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void Given_Token_When_Hash_Then_Hash_And_Verify_Then_Result_Should_Be_True()
|
||||
public void Given_Token_When_Hash_Then_Verify_Should_Return_True()
|
||||
{
|
||||
// Arrange
|
||||
string token = _fixture.Create<string>();
|
||||
|
||||
// Act
|
||||
|
||||
// Act
|
||||
string hash = _jwtTokenHasher.HashToken(token);
|
||||
|
||||
var result = _jwtTokenHasher.VerifyToken(token, hash);
|
||||
|
||||
// Assert
|
||||
|
||||
// Assert
|
||||
Assert.That(hash, Is.Not.EqualTo(token));
|
||||
Assert.That(result, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Given_Token_NotToken_When_Hash_Should_Not_Be_True_Then_Result_Should_Be_False()
|
||||
public void Given_Invalid_Token_When_Verify_Should_Return_False()
|
||||
{
|
||||
// Arrange
|
||||
// Arrange
|
||||
string token = _fixture.Create<string>();
|
||||
string notToken = _fixture.Create<string>();
|
||||
|
||||
// Act
|
||||
|
||||
// Act
|
||||
string hash = _jwtTokenHasher.HashToken(token);
|
||||
|
||||
var result = _jwtTokenHasher.VerifyToken(notToken, hash);
|
||||
|
||||
// Assert
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Given_Same_Token_When_Hash_Multiple_Times_Should_Be_Equal()
|
||||
{
|
||||
// Arrange
|
||||
string token = _fixture.Create<string>();
|
||||
|
||||
// Act
|
||||
string hash1 = _jwtTokenHasher.HashToken(token);
|
||||
string hash2 = _jwtTokenHasher.HashToken(token);
|
||||
|
||||
// Assert
|
||||
Assert.That(hash1, Is.EqualTo(hash2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Given_Different_Tokens_When_Hash_Should_Be_Different()
|
||||
{
|
||||
// Arrange
|
||||
string token1 = _fixture.Create<string>();
|
||||
string token2 = _fixture.Create<string>();
|
||||
|
||||
// Act
|
||||
string hash1 = _jwtTokenHasher.HashToken(token1);
|
||||
string hash2 = _jwtTokenHasher.HashToken(token2);
|
||||
|
||||
// Assert
|
||||
Assert.That(hash1, Is.Not.EqualTo(hash2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Given_Null_Secret_In_Config_Should_Use_Default_Secret()
|
||||
{
|
||||
// Arrange
|
||||
var emptyConfig = new ConfigurationBuilder().Build();
|
||||
var hasherWithDefaultSecret = new JwtTokenHasher(emptyConfig);
|
||||
|
||||
string token = _fixture.Create<string>();
|
||||
|
||||
// Act
|
||||
string hash = hasherWithDefaultSecret.HashToken(token);
|
||||
var result = hasherWithDefaultSecret.VerifyToken(token, hash);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.True);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using AutoFixture;
|
||||
using Govor.Application.Exceptions.FriendsService;
|
||||
using Govor.Application.Interfaces;
|
||||
using Govor.Application.Interfaces.Friends;
|
||||
using Govor.Application.Services.Friends;
|
||||
using Govor.Core.Models;
|
||||
@@ -14,8 +15,8 @@ namespace Govor.Application.Tests.Services.Friends;
|
||||
public class FriendRequestCommandServiceTests
|
||||
{
|
||||
private Fixture _fixture;
|
||||
private Mock<IUsersRepository> _usersRepositoryMock;
|
||||
private Mock<IFriendshipsRepository> _friendshipsRepositoryMock;
|
||||
private Mock<IUserPrivateChatsCreator> _privateChatsCreatorMock;
|
||||
private IFriendRequestCommandService _service;
|
||||
|
||||
[SetUp]
|
||||
@@ -27,11 +28,11 @@ public class FriendRequestCommandServiceTests
|
||||
.ToList()
|
||||
.ForEach(b => _fixture.Behaviors.Remove(b));
|
||||
_fixture.Behaviors.Add(new OmitOnRecursionBehavior());
|
||||
|
||||
_usersRepositoryMock = new Mock<IUsersRepository>();
|
||||
|
||||
_friendshipsRepositoryMock = new Mock<IFriendshipsRepository>();
|
||||
|
||||
_service = new FriendRequestCommandService(_friendshipsRepositoryMock.Object);
|
||||
_privateChatsCreatorMock = new Mock<IUserPrivateChatsCreator>();
|
||||
|
||||
_service = new FriendRequestCommandService(_friendshipsRepositoryMock.Object, _privateChatsCreatorMock.Object);
|
||||
}
|
||||
|
||||
// SendFriendRequestAsync
|
||||
@@ -55,9 +56,17 @@ public class FriendRequestCommandServiceTests
|
||||
var fromUserId = Guid.NewGuid();
|
||||
var toUserId = Guid.NewGuid();
|
||||
|
||||
var existingFriendship = new Friendship
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
RequesterId = fromUserId,
|
||||
AddresseeId = toUserId,
|
||||
Status = FriendshipStatus.Pending
|
||||
};
|
||||
|
||||
_friendshipsRepositoryMock
|
||||
.Setup(repo => repo.Exist(fromUserId, toUserId))
|
||||
.Returns(true);
|
||||
.Setup(repo => repo.GetFriendshipAsync(fromUserId, toUserId))
|
||||
.ReturnsAsync(existingFriendship);
|
||||
|
||||
// Act & Assert
|
||||
Assert.ThrowsAsync<RequestAlreadySentException>(() =>
|
||||
@@ -91,17 +100,30 @@ public class FriendRequestCommandServiceTests
|
||||
|
||||
// AcceptFriendRequestAsync
|
||||
[Test]
|
||||
public async Task AcceptFriendRequestAsync_ValidRequest_CallsUpdateAsync()
|
||||
public async Task AcceptFriendRequestAsync_ValidRequest_CallsUpdateAsync_AndCreatesPrivateChat()
|
||||
{
|
||||
// Arrange
|
||||
var friendship = _fixture.Build<Friendship>()
|
||||
.With(f => f.Status, FriendshipStatus.Pending)
|
||||
.Create();
|
||||
|
||||
var privateChat = new PrivateChat
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
UserAId = friendship.AddresseeId,
|
||||
UserBId = friendship.RequesterId
|
||||
};
|
||||
|
||||
|
||||
_friendshipsRepositoryMock
|
||||
.Setup(r => r.GetByIdAsync(friendship.Id))
|
||||
.ReturnsAsync(friendship);
|
||||
|
||||
// Act: вызываем именно Accept, не Send
|
||||
_privateChatsCreatorMock
|
||||
.Setup(p => p.CreateAsync(friendship.AddresseeId, friendship.RequesterId))
|
||||
.ReturnsAsync(privateChat);
|
||||
|
||||
// Act
|
||||
await _service.AcceptAsync(friendship.Id, friendship.AddresseeId);
|
||||
|
||||
// Assert
|
||||
@@ -111,6 +133,11 @@ public class FriendRequestCommandServiceTests
|
||||
f.AddresseeId == friendship.AddresseeId &&
|
||||
f.Status == FriendshipStatus.Accepted
|
||||
)), Times.Once);
|
||||
|
||||
_privateChatsCreatorMock.Verify(p => p.CreateAsync(
|
||||
friendship.AddresseeId,
|
||||
friendship.RequesterId
|
||||
), Times.Once);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -21,9 +21,10 @@ public class MessageCommandServiceTests
|
||||
private Mock<IMessagesRepository> _mockMessagesRepo;
|
||||
private Mock<IUsersRepository> _mockUsersRepo;
|
||||
private Mock<IGroupsRepository> _mockGroupsRepo;
|
||||
private Mock<IPrivateChatsRepository> _mockPrivateChatsRepo;
|
||||
private Mock<IVerifyFriendship> _mockVerifyFriendship;
|
||||
private Mock<IPrivateChatsRepository> _mockPrivateChats;
|
||||
private Mock<IMediaService> _mockMediaService;
|
||||
private Mock<IMediaService> _mockMediaService;
|
||||
private Mock<IUserPrivateChatsCreator> _mockUserPrivateChatCreator;
|
||||
private Mock<ILogger<MessageCommandService>> _mockLogger;
|
||||
private MessageCommandService _messageService;
|
||||
|
||||
@@ -33,17 +34,19 @@ public class MessageCommandServiceTests
|
||||
_mockMessagesRepo = new Mock<IMessagesRepository>();
|
||||
_mockUsersRepo = new Mock<IUsersRepository>();
|
||||
_mockGroupsRepo = new Mock<IGroupsRepository>();
|
||||
_mockPrivateChatsRepo = new Mock<IPrivateChatsRepository>();
|
||||
_mockVerifyFriendship = new Mock<IVerifyFriendship>();
|
||||
_mockPrivateChats = new Mock<IPrivateChatsRepository>();
|
||||
_mockMediaService = new Mock<IMediaService>();
|
||||
_mockUserPrivateChatCreator = new Mock<IUserPrivateChatsCreator>();
|
||||
_mockLogger = new Mock<ILogger<MessageCommandService>>();
|
||||
|
||||
_messageService = new MessageCommandService(
|
||||
_mockMessagesRepo.Object,
|
||||
_mockUsersRepo.Object,
|
||||
_mockGroupsRepo.Object,
|
||||
_mockPrivateChatsRepo.Object,
|
||||
_mockUserPrivateChatCreator.Object,
|
||||
_mockVerifyFriendship.Object,
|
||||
_mockPrivateChats.Object,
|
||||
_mockMediaService.Object,
|
||||
_mockLogger.Object);
|
||||
}
|
||||
@@ -56,7 +59,16 @@ public class MessageCommandServiceTests
|
||||
// Arrange
|
||||
var senderId = Guid.NewGuid();
|
||||
var recipientId = Guid.NewGuid();
|
||||
var sendMessageParams = new SendMessage("Hello",
|
||||
|
||||
var privateChat = new PrivateChat
|
||||
{
|
||||
Id = recipientId,
|
||||
UserAId = senderId,
|
||||
UserBId = Guid.NewGuid()
|
||||
};
|
||||
|
||||
var sendParams = new SendMessage(
|
||||
"Hello",
|
||||
null,
|
||||
recipientId,
|
||||
RecipientType.User,
|
||||
@@ -64,26 +76,28 @@ public class MessageCommandServiceTests
|
||||
DateTime.UtcNow,
|
||||
new List<SendMedia>());
|
||||
|
||||
_mockUsersRepo.Setup(r => r.ExistsByIdAsync(recipientId)).ReturnsAsync(true);
|
||||
_mockVerifyFriendship.Setup(v => v.VerifyAsync(senderId, recipientId)).Returns(Task.CompletedTask);
|
||||
_mockMessagesRepo.Setup(r => r.AddAsync(It.IsAny<Message>())).Returns(Task.CompletedTask);
|
||||
_mockPrivateChats.Setup(c => c.Exist(senderId, recipientId)).Returns(true);
|
||||
_mockPrivateChats.Setup(c => c.GetByMembersAsync(senderId, recipientId)).ReturnsAsync(new PrivateChat(){Id = recipientId});
|
||||
|
||||
_mockPrivateChatsRepo
|
||||
.Setup(r => r.GetByIdAsync(recipientId))
|
||||
.ReturnsAsync(privateChat);
|
||||
|
||||
_mockMessagesRepo
|
||||
.Setup(r => r.AddAsync(It.IsAny<Message>()))
|
||||
.Returns(Task.CompletedTask);
|
||||
|
||||
// Act
|
||||
var result = await _messageService.SendMessageAsync(sendMessageParams);
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
var result = await _messageService.SendMessageAsync(sendParams);
|
||||
|
||||
// Assert
|
||||
Assert.That(result.IsSuccess, Is.True);
|
||||
Assert.That(result.Exception, Is.Null);
|
||||
|
||||
_mockMessagesRepo.Verify(r => r.AddAsync(It.Is<Message>(m =>
|
||||
m.SenderId == senderId &&
|
||||
m.RecipientId == recipientId &&
|
||||
|
||||
_mockMessagesRepo.Verify(r => r.AddAsync(It.Is<Message>(m =>
|
||||
m.SenderId == senderId &&
|
||||
m.RecipientId == recipientId &&
|
||||
m.RecipientType == RecipientType.User &&
|
||||
m.EncryptedContent == "Hello")), Times.Once);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public async Task SendMessageAsync_ToUser_When_AttachMediaThrowsException_ReturnsFailure()
|
||||
{
|
||||
@@ -92,44 +106,43 @@ public class MessageCommandServiceTests
|
||||
var recipientId = Guid.NewGuid();
|
||||
var sendMediaId = Guid.NewGuid();
|
||||
|
||||
var sendMessageParams = new SendMessage(
|
||||
var privateChat = new PrivateChat
|
||||
{
|
||||
Id = recipientId,
|
||||
UserAId = senderId,
|
||||
UserBId = recipientId
|
||||
};
|
||||
|
||||
var sendParams = new SendMessage(
|
||||
"Hello",
|
||||
null,
|
||||
recipientId,
|
||||
RecipientType.User,
|
||||
senderId,
|
||||
DateTime.UtcNow,
|
||||
new List<SendMedia> { new SendMedia(sendMediaId, string.Empty) });
|
||||
new List<SendMedia>
|
||||
{
|
||||
new SendMedia(sendMediaId, string.Empty)
|
||||
});
|
||||
|
||||
_mockUsersRepo.Setup(r => r.ExistsByIdAsync(recipientId)).ReturnsAsync(true);
|
||||
_mockVerifyFriendship.Setup(v => v.VerifyAsync(senderId, recipientId)).Returns(Task.CompletedTask);
|
||||
_mockMessagesRepo.Setup(r => r.AddAsync(It.IsAny<Message>())).Returns(Task.CompletedTask);
|
||||
_mockPrivateChats.Setup(c => c.Exist(senderId, recipientId)).Returns(true);
|
||||
_mockPrivateChats.Setup(c => c.GetByMembersAsync(senderId, recipientId))
|
||||
.ReturnsAsync(new PrivateChat { Id = recipientId });
|
||||
_mockPrivateChatsRepo
|
||||
.Setup(r => r.GetByIdAsync(recipientId))
|
||||
.ReturnsAsync(privateChat);
|
||||
|
||||
// !
|
||||
_mockMediaService
|
||||
.Setup(m => m.AttachToMessageAsync(sendMediaId, It.IsAny<Guid>()))
|
||||
.ThrowsAsync(new Exception("Unexpected DB error"));
|
||||
|
||||
// Act
|
||||
var result = await _messageService.SendMessageAsync(sendMessageParams);
|
||||
var result = await _messageService.SendMessageAsync(sendParams);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.IsSuccess, Is.False);
|
||||
Assert.That(result.Exception, Is.Not.Null);
|
||||
Assert.That(result.Exception.Message, Is.EqualTo("Unexpected DB error"));
|
||||
Assert.That(result.Exception!.Message, Is.EqualTo("Unexpected DB error"));
|
||||
|
||||
// Проверяем, что сообщение не было сохранено
|
||||
_mockMessagesRepo.Verify(r => r.AddAsync(It.IsAny<Message>()), Times.Never);
|
||||
|
||||
// Проверяем, что метод прикрепления медиа вызывался
|
||||
_mockMediaService.Verify(m => m.AttachToMessageAsync(sendMediaId, It.IsAny<Guid>()), Times.Once);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public async Task SendMessageAsync_ToGroup_Success()
|
||||
{
|
||||
@@ -162,13 +175,14 @@ public class MessageCommandServiceTests
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task SendMessageAsync_ToUser_RecipientNotFound_ReturnsFailure()
|
||||
public async Task SendMessageAsync_ToUser_PrivateChatNotFound_ReturnsFailure()
|
||||
{
|
||||
// Arrange
|
||||
var senderId = Guid.NewGuid();
|
||||
var recipientId = Guid.NewGuid();
|
||||
|
||||
var sendMessageParams = new SendMessage("Hello",
|
||||
|
||||
var sendParams = new SendMessage(
|
||||
"Hello",
|
||||
null,
|
||||
recipientId,
|
||||
RecipientType.User,
|
||||
@@ -176,50 +190,18 @@ public class MessageCommandServiceTests
|
||||
DateTime.UtcNow,
|
||||
new List<SendMedia>());
|
||||
|
||||
_mockUsersRepo.Setup(r => r.ExistsByIdAsync(recipientId)).ReturnsAsync(false);
|
||||
_mockPrivateChatsRepo
|
||||
.Setup(r => r.GetByIdAsync(recipientId))
|
||||
.ReturnsAsync((PrivateChat?)null);
|
||||
|
||||
// Act
|
||||
var result = await _messageService.SendMessageAsync(sendMessageParams);
|
||||
var result = await _messageService.SendMessageAsync(sendParams);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.IsSuccess, Is.False);
|
||||
Assert.That(result.Exception, Is.Not.Null);
|
||||
Assert.That(result.Exception,Is.TypeOf<KeyNotFoundException>());
|
||||
Assert.That(result.Exception, Is.TypeOf<KeyNotFoundException>());
|
||||
Assert.That(result.Message, Is.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task SendMessageAsync_ToUser_FriendshipVerificationFails_ReturnsFailure()
|
||||
{
|
||||
// Arrange
|
||||
var senderId = Guid.NewGuid();
|
||||
var recipientId = Guid.NewGuid();
|
||||
|
||||
var sendMessageParams = new SendMessage("Hello",
|
||||
null,
|
||||
recipientId,
|
||||
RecipientType.User,
|
||||
senderId,
|
||||
DateTime.UtcNow,
|
||||
new List<SendMedia>()
|
||||
);
|
||||
|
||||
_mockUsersRepo.Setup(r => r.ExistsByIdAsync(recipientId)).ReturnsAsync(true);
|
||||
_mockVerifyFriendship.Setup(v => v.VerifyAsync(senderId, recipientId)).ThrowsAsync(new FriendshipException("Not friends"));
|
||||
|
||||
// Act
|
||||
var result = await _messageService.SendMessageAsync(sendMessageParams);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.IsSuccess, Is.False);
|
||||
Assert.That(result.Exception, Is.Not.Null);
|
||||
Assert.That(result.Exception,Is.TypeOf<FriendshipException>());
|
||||
Assert.That(result.Message, Is.Null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Test for EditMessageAsync action
|
||||
[Test]
|
||||
|
||||
@@ -43,36 +43,51 @@ public class MessagesLoaderTests
|
||||
// Arrange
|
||||
var chatId = Guid.NewGuid();
|
||||
|
||||
_privateChatsRepoMock.Setup(r => r.Exist(_currentUserId, _otherUserId)).Returns(true);
|
||||
_privateChatsRepoMock.Setup(r => r.GetByMembersAsync(_currentUserId, _otherUserId))
|
||||
.ReturnsAsync(new PrivateChat() { Id = chatId });
|
||||
_privateChatsRepoMock
|
||||
.Setup(r => r.Exist(chatId))
|
||||
.Returns(true);
|
||||
|
||||
var messages = new List<Message>
|
||||
{
|
||||
new() { Id = Guid.NewGuid(), RecipientId = chatId, RecipientType = RecipientType.User }
|
||||
new()
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
RecipientId = chatId,
|
||||
RecipientType = RecipientType.User,
|
||||
SentAt = DateTime.UtcNow
|
||||
}
|
||||
};
|
||||
|
||||
await _dbContext.Messages.AddRangeAsync(messages);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
|
||||
// Act
|
||||
var result = await _loader.LoadMessagesInUserChat(_currentUserId, _otherUserId, null);
|
||||
var result = await _loader.LoadMessagesInUserChat(
|
||||
chatId,
|
||||
_currentUserId,
|
||||
null);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Has.Count.EqualTo(1));
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public async Task LoadLastMessagesInUserChat_ReturnsEmpty_WhenNoMessages()
|
||||
{
|
||||
// Arrange
|
||||
_privateChatsRepoMock.Setup(r => r.Exist(_currentUserId, _otherUserId)).Returns(true);
|
||||
_privateChatsRepoMock.Setup(r => r.GetByMembersAsync(_currentUserId, _otherUserId))
|
||||
.ReturnsAsync(new PrivateChat { Id = Guid.NewGuid() });
|
||||
// Act
|
||||
var result = await _loader.LoadMessagesInUserChat(_currentUserId, _otherUserId, null);
|
||||
// Arrange
|
||||
var chatId = Guid.NewGuid();
|
||||
|
||||
// Assert
|
||||
_privateChatsRepoMock
|
||||
.Setup(r => r.Exist(chatId))
|
||||
.Returns(true);
|
||||
|
||||
// Act
|
||||
var result = await _loader.LoadMessagesInUserChat(
|
||||
chatId,
|
||||
_currentUserId,
|
||||
null);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
|
||||
@@ -83,7 +98,7 @@ public class MessagesLoaderTests
|
||||
var ex = Assert.ThrowsAsync<ArgumentException>(async () =>
|
||||
await _loader.LoadMessagesInUserChat(Guid.Empty, _currentUserId, null));
|
||||
|
||||
Assert.That(ex.Message, Does.Contain("User id cannot be empty"));
|
||||
Assert.That(ex.Message, Does.Contain("PrivateChatId id cannot be empty"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
using Govor.Application.Interfaces.PushNotifications;
|
||||
using Govor.Application.Interfaces.PushNotifications.Models;
|
||||
using Govor.Application.Services.PushNotifications;
|
||||
using Govor.Core.Repositories.PushTokens;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
|
||||
namespace Govor.Application.Tests.Services.PushNotifications;
|
||||
|
||||
[TestFixture]
|
||||
public class PushNotificationServiceTests
|
||||
{
|
||||
private Mock<IPushNotificationProvider> _providerMock;
|
||||
private Mock<IPushTokenRepository> _tokenRepoMock;
|
||||
private Mock<ILogger<PushNotificationService>> _loggerMock;
|
||||
|
||||
private PushNotificationService _service;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_providerMock = new Mock<IPushNotificationProvider>(MockBehavior.Strict);
|
||||
_tokenRepoMock = new Mock<IPushTokenRepository>(MockBehavior.Strict);
|
||||
_loggerMock = new Mock<ILogger<PushNotificationService>>();
|
||||
|
||||
_service = new PushNotificationService(
|
||||
_providerMock.Object,
|
||||
_tokenRepoMock.Object,
|
||||
_loggerMock.Object);
|
||||
}
|
||||
|
||||
#region SendToUserAsync
|
||||
|
||||
[Test]
|
||||
public async Task SendToUserAsync_NoTokens_DoesNotCallProvider()
|
||||
{
|
||||
// Arrange
|
||||
var userId = Guid.NewGuid();
|
||||
|
||||
_tokenRepoMock
|
||||
.Setup(r => r.GetActiveTokensAsync(userId))
|
||||
.ReturnsAsync(new List<string>());
|
||||
|
||||
// Act
|
||||
await _service.SendToUserAsync(userId, "title", "body", "chat");
|
||||
|
||||
// Assert
|
||||
_providerMock.Verify(
|
||||
p => p.SendMulticastAsync(It.IsAny<IReadOnlyList<string>>(), It.IsAny<PushMessage>()),
|
||||
Times.Never);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task SendToUserAsync_SuccessfulSend_CallsProvider()
|
||||
{
|
||||
// Arrange
|
||||
var userId = Guid.NewGuid();
|
||||
var tokens = new List<string> { "t1", "t2" };
|
||||
|
||||
_tokenRepoMock
|
||||
.Setup(r => r.GetActiveTokensAsync(userId))
|
||||
.ReturnsAsync(tokens);
|
||||
|
||||
_providerMock
|
||||
.Setup(p => p.SendMulticastAsync(tokens, It.IsAny<PushMessage>()))
|
||||
.ReturnsAsync(new SendPushResult(0, 0, []));
|
||||
|
||||
// Act
|
||||
await _service.SendToUserAsync(userId, "title", "body", "chat");
|
||||
|
||||
// Assert
|
||||
_providerMock.Verify(
|
||||
p => p.SendMulticastAsync(tokens, It.IsAny<PushMessage>()),
|
||||
Times.Once);
|
||||
|
||||
_tokenRepoMock.Verify(
|
||||
r => r.RemoveTokensAsync(It.IsAny<IEnumerable<string>>()),
|
||||
Times.Never);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task SendToUserAsync_WithFailures_RemovesInvalidTokens()
|
||||
{
|
||||
// Arrange
|
||||
var userId = Guid.NewGuid();
|
||||
var tokens = new List<string> { "t1", "t2" };
|
||||
var failed = new List<string> { "t2" };
|
||||
|
||||
_tokenRepoMock
|
||||
.Setup(r => r.GetActiveTokensAsync(userId))
|
||||
.ReturnsAsync(tokens);
|
||||
|
||||
_providerMock
|
||||
.Setup(p => p.SendMulticastAsync(tokens, It.IsAny<PushMessage>()))
|
||||
.ReturnsAsync(new SendPushResult(0, 1, failed));
|
||||
|
||||
_tokenRepoMock
|
||||
.Setup(r => r.RemoveTokensAsync(failed))
|
||||
.Returns(Task.CompletedTask);
|
||||
|
||||
// Act
|
||||
await _service.SendToUserAsync(userId, "title", "body", "chat");
|
||||
|
||||
// Assert
|
||||
_tokenRepoMock.Verify(r => r.RemoveTokensAsync(failed), Times.Once);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region SendToUsersAsync
|
||||
|
||||
[Test]
|
||||
public async Task SendToUsersAsync_NoTokens_DoesNotCallProvider()
|
||||
{
|
||||
// Arrange
|
||||
var users = new[] { Guid.NewGuid() };
|
||||
|
||||
_tokenRepoMock
|
||||
.Setup(r => r.GetActiveTokensUsersAsync(users))
|
||||
.ReturnsAsync(new List<string>());
|
||||
|
||||
// Act
|
||||
await _service.SendToUsersAsync(users, "title", "body", "chat");
|
||||
|
||||
// Assert
|
||||
_providerMock.Verify(
|
||||
p => p.SendMulticastAsync(It.IsAny<IReadOnlyList<string>>(), It.IsAny<PushMessage>()),
|
||||
Times.Never);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region SendToSessionAsync
|
||||
|
||||
[Test]
|
||||
public async Task SendToSessionAsync_NoToken_DoesNothing()
|
||||
{
|
||||
// Arrange
|
||||
var sessionId = Guid.NewGuid();
|
||||
|
||||
_tokenRepoMock
|
||||
.Setup(r => r.GetActiveTokenBySessionAsync(sessionId))
|
||||
.ReturnsAsync("");
|
||||
|
||||
// Act
|
||||
await _service.SendToSessionAsync(sessionId, "title", "body", "chat");
|
||||
|
||||
// Assert
|
||||
_providerMock.Verify(
|
||||
p => p.SendToTokenAsync(It.IsAny<string>(), It.IsAny<PushMessage>()),
|
||||
Times.Never);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task SendToSessionAsync_WithFailure_RemovesToken()
|
||||
{
|
||||
// Arrange
|
||||
var sessionId = Guid.NewGuid();
|
||||
var token = "t1";
|
||||
|
||||
_tokenRepoMock
|
||||
.Setup(r => r.GetActiveTokenBySessionAsync(sessionId))
|
||||
.ReturnsAsync(token);
|
||||
|
||||
_providerMock
|
||||
.Setup(p => p.SendToTokenAsync(token, It.IsAny<PushMessage>()))
|
||||
.ReturnsAsync(new SendPushResult(0, 1, [token]));
|
||||
|
||||
_tokenRepoMock
|
||||
.Setup(r => r.RemoveTokensAsync(It.IsAny<IEnumerable<string>>()))
|
||||
.Returns(Task.CompletedTask);
|
||||
|
||||
// Act
|
||||
await _service.SendToSessionAsync(sessionId, "title", "body", "chat");
|
||||
|
||||
// Assert
|
||||
_tokenRepoMock.Verify(
|
||||
r => r.RemoveTokensAsync(It.Is<IEnumerable<string>>(x => x.Contains(token))),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
using AutoFixture;
|
||||
using Govor.Application.Interfaces;
|
||||
using Govor.Application.Services;
|
||||
using Govor.Core.Models;
|
||||
using Govor.Core.Repositories.PrivateChats;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
|
||||
namespace Govor.Application.Tests.Services;
|
||||
|
||||
[TestFixture]
|
||||
public class UserPrivateChatsCreatorTests
|
||||
{
|
||||
private Fixture _fixture;
|
||||
private Mock<ILogger<UserPrivateChatsCreator>> _mockLogger;
|
||||
private Mock<IPrivateChatsRepository> _mockPrivateChats;
|
||||
private Mock<IPrivateChatGroupManager> _mockPrivateChatGroupManager;
|
||||
private IUserPrivateChatsCreator _service;
|
||||
|
||||
[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<UserPrivateChatsCreator>>();
|
||||
_mockPrivateChats = new Mock<IPrivateChatsRepository>();
|
||||
_mockPrivateChatGroupManager = new Mock<IPrivateChatGroupManager>();
|
||||
|
||||
_service = new UserPrivateChatsCreator(
|
||||
_mockPrivateChats.Object,
|
||||
_mockPrivateChatGroupManager.Object,
|
||||
_mockLogger.Object);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task CreateAsync_ShouldCreateNewChat_WhenChatDoesNotExist()
|
||||
{
|
||||
// Arrange
|
||||
var userA = Guid.NewGuid();
|
||||
var userB = Guid.NewGuid();
|
||||
|
||||
_mockPrivateChats
|
||||
.Setup(x => x.Exist(userA, userB))
|
||||
.Returns(false);
|
||||
|
||||
PrivateChat? addedChat = null;
|
||||
|
||||
_mockPrivateChats
|
||||
.Setup(x => x.AddAsync(It.IsAny<PrivateChat>()))
|
||||
.Callback<PrivateChat>(chat => addedChat = chat)
|
||||
.Returns(Task.CompletedTask);
|
||||
|
||||
// Act
|
||||
var result = await _service.CreateAsync(userA, userB);
|
||||
|
||||
// Assert
|
||||
_mockPrivateChats.Verify(x => x.AddAsync(It.IsAny<PrivateChat>()), Times.Once);
|
||||
_mockPrivateChatGroupManager.Verify(x => x.AddUsersToPrivateChatGroupAsync(It.IsAny<PrivateChat>()), Times.Once);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.UserAId, Is.EqualTo(userA));
|
||||
Assert.That(result.UserBId, Is.EqualTo(userB));
|
||||
Assert.That(result.Id, Is.Not.EqualTo(Guid.Empty));
|
||||
|
||||
Assert.That(addedChat, Is.Not.Null);
|
||||
Assert.That(addedChat!.Id, Is.EqualTo(result.Id));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task CreateAsync_ShouldReturnExistingChat_WhenChatAlreadyExists()
|
||||
{
|
||||
// Arrange
|
||||
var userA = Guid.NewGuid();
|
||||
var userB = Guid.NewGuid();
|
||||
|
||||
var existingChat = _fixture.Build<PrivateChat>()
|
||||
.With(x => x.UserAId, userA)
|
||||
.With(x => x.UserBId, userB)
|
||||
.Create();
|
||||
|
||||
_mockPrivateChats
|
||||
.Setup(x => x.Exist(userA, userB))
|
||||
.Returns(true);
|
||||
|
||||
_mockPrivateChats
|
||||
.Setup(x => x.GetByMembersAsync(userA, userB))
|
||||
.ReturnsAsync(existingChat);
|
||||
|
||||
// Act
|
||||
var result = await _service.CreateAsync(userA, userB);
|
||||
|
||||
// Assert
|
||||
_mockPrivateChats.Verify(x => x.AddAsync(It.IsAny<PrivateChat>()), Times.Never);
|
||||
|
||||
_mockPrivateChatGroupManager.Verify(
|
||||
x => x.AddUsersToPrivateChatGroupAsync(It.IsAny<PrivateChat>()),
|
||||
Times.Never);
|
||||
|
||||
_mockPrivateChats.Verify(x => x.GetByMembersAsync(userA, userB), Times.Once);
|
||||
|
||||
Assert.That(result, Is.EqualTo(existingChat));
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using Govor.Application.Services.UserSessions;
|
||||
using Govor.Core.Models;
|
||||
using Govor.Core.Models.Users;
|
||||
using Govor.Core.Repositories.PushTokens;
|
||||
using Govor.Core.Repositories.UserSessionsRepository;
|
||||
using Govor.Data.Repositories.Exceptions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@@ -14,6 +15,7 @@ public class UserSessionRevokerTests
|
||||
{
|
||||
private Mock<IUserSessionsRepository> _sessionsRepositoryMock;
|
||||
private Mock<ILogger<UserSessionRevoker>> _loggerMock;
|
||||
private Mock<IPushTokenRepository> _pushTokenRepositoryMock;
|
||||
private UserSessionRevoker _revoker;
|
||||
|
||||
[SetUp]
|
||||
@@ -21,7 +23,8 @@ public class UserSessionRevokerTests
|
||||
{
|
||||
_sessionsRepositoryMock = new Mock<IUserSessionsRepository>();
|
||||
_loggerMock = new Mock<ILogger<UserSessionRevoker>>();
|
||||
_revoker = new UserSessionRevoker(_sessionsRepositoryMock.Object, _loggerMock.Object);
|
||||
_pushTokenRepositoryMock = new Mock<IPushTokenRepository>();
|
||||
_revoker = new UserSessionRevoker(_sessionsRepositoryMock.Object, _pushTokenRepositoryMock.Object, _loggerMock.Object);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -39,6 +42,7 @@ public class UserSessionRevokerTests
|
||||
// Assert
|
||||
Assert.That(session.IsRevoked, Is.True);
|
||||
_sessionsRepositoryMock.Verify(r => r.UpdateAsync(session), Times.Once());
|
||||
_pushTokenRepositoryMock.Verify(r => r.DeactivateTokenBySessionAsync(sessionId), Times.Once());
|
||||
_loggerMock.VerifyNoOtherCalls();
|
||||
}
|
||||
|
||||
@@ -56,13 +60,16 @@ public class UserSessionRevokerTests
|
||||
var ex = Assert.ThrowsAsync<UnauthorizedAccessException>(() =>
|
||||
_revoker.CloseSessionByIdAsync(sessionId, differentUserId));
|
||||
Assert.That(ex.Message, Contains.Substring($"User {differentUserId} does not belong to this session {sessionId}"));
|
||||
|
||||
_loggerMock.Verify(l => l.Log(
|
||||
LogLevel.Warning,
|
||||
It.IsAny<EventId>(),
|
||||
It.IsAny<It.IsAnyType>(),
|
||||
It.IsAny<Exception>(),
|
||||
It.IsAny<Func<It.IsAnyType, Exception, string>>()), Times.Once());
|
||||
|
||||
_sessionsRepositoryMock.Verify(r => r.UpdateAsync(It.IsAny<UserSession>()), Times.Never());
|
||||
_pushTokenRepositoryMock.Verify(r => r.DeactivateTokenBySessionAsync(sessionId), Times.Never());
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -79,6 +86,7 @@ public class UserSessionRevokerTests
|
||||
|
||||
// Assert
|
||||
_sessionsRepositoryMock.Verify(r => r.UpdateAsync(It.IsAny<UserSession>()), Times.Never());
|
||||
_pushTokenRepositoryMock.Verify(r => r.DeactivateTokenBySessionAsync(sessionId), Times.Never());
|
||||
_loggerMock.VerifyNoOtherCalls();
|
||||
}
|
||||
|
||||
@@ -102,6 +110,7 @@ public class UserSessionRevokerTests
|
||||
It.IsAny<Exception>(),
|
||||
It.IsAny<Func<It.IsAnyType, Exception, string>>()), Times.Once());
|
||||
_sessionsRepositoryMock.Verify(r => r.UpdateAsync(It.IsAny<UserSession>()), Times.Never());
|
||||
_pushTokenRepositoryMock.Verify(r => r.DeactivateTokenBySessionAsync(sessionId), Times.Never());
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -126,7 +135,11 @@ public class UserSessionRevokerTests
|
||||
Assert.That(sessions[2].IsRevoked, Is.True);
|
||||
_sessionsRepositoryMock.Verify(r => r.UpdateAsync(sessions[0]), Times.Once());
|
||||
_sessionsRepositoryMock.Verify(r => r.UpdateAsync(sessions[2]), Times.Once());
|
||||
_pushTokenRepositoryMock.Verify(r => r.DeactivateTokenBySessionAsync(sessions[0].Id), Times.Once());
|
||||
_pushTokenRepositoryMock.Verify(r => r.DeactivateTokenBySessionAsync(sessions[2].Id), Times.Once());
|
||||
|
||||
_sessionsRepositoryMock.Verify(r => r.UpdateAsync(sessions[1]), Times.Never());
|
||||
_pushTokenRepositoryMock.Verify(r => r.DeactivateTokenBySessionAsync(sessions[1].Id), Times.Never);
|
||||
_loggerMock.VerifyNoOtherCalls();
|
||||
}
|
||||
|
||||
@@ -148,6 +161,8 @@ public class UserSessionRevokerTests
|
||||
It.IsAny<It.IsAnyType>(),
|
||||
It.IsAny<Exception>(),
|
||||
It.IsAny<Func<It.IsAnyType, Exception, string>>()), Times.Once());
|
||||
|
||||
_pushTokenRepositoryMock.Verify(r => r.DeactivateTokenBySessionAsync(It.IsAny<Guid>()), Times.Never);
|
||||
_sessionsRepositoryMock.Verify(r => r.UpdateAsync(It.IsAny<UserSession>()), Times.Never());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user