using Govor.Application.Exceptions.VerifyFriendship; using Govor.Application.Interfaces; using Govor.Application.Interfaces.Messages.Parameters; using Govor.Application.Services.Messages; using Govor.Core.Models; using Govor.Core.Models.Messages; using Govor.Core.Repositories.Groups; using Govor.Core.Repositories.Messages; using Govor.Core.Repositories.PrivateChats; using Govor.Core.Repositories.Users; using Govor.Data.Repositories.Exceptions; using Microsoft.Extensions.Logging; using Moq; namespace Govor.Application.Tests.Services.Messages; [TestFixture] public class MessageCommandServiceTests { private Mock _mockMessagesRepo; private Mock _mockUsersRepo; private Mock _mockGroupsRepo; private Mock _mockVerifyFriendship; private Mock _mockPrivateChats; private Mock> _mockLogger; private MessageCommandService _messageService; [SetUp] public void SetUp() { _mockMessagesRepo = new Mock(); _mockUsersRepo = new Mock(); _mockGroupsRepo = new Mock(); _mockVerifyFriendship = new Mock(); _mockPrivateChats = new Mock(); _mockLogger = new Mock>(); _messageService = new MessageCommandService( _mockMessagesRepo.Object, _mockUsersRepo.Object, _mockGroupsRepo.Object, _mockVerifyFriendship.Object, _mockPrivateChats.Object, _mockLogger.Object); } // Test for SendMessageAsync action [Test] public async Task SendMessageAsync_ToUser_Success() { // Arrange var senderId = Guid.NewGuid(); var recipientId = Guid.NewGuid(); var sendMessageParams = new SendMessage("Hello", null, recipientId, RecipientType.User, senderId, DateTime.UtcNow, new List()); _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())).Returns(Task.CompletedTask); _mockPrivateChats.Setup(c => c.Exist(senderId, recipientId)).Returns(true); _mockPrivateChats.Setup(c => c.GetByMembersAsync(senderId, recipientId)).ReturnsAsync(new PrivateChat(){Id = recipientId}); // Act var result = await _messageService.SendMessageAsync(sendMessageParams); // Assert Assert.That(result, Is.Not.Null); Assert.That(result.IsSuccess, Is.True); Assert.That(result.Exception, Is.Null); _mockMessagesRepo.Verify(r => r.AddAsync(It.Is(m => m.SenderId == senderId && m.RecipientId == recipientId && m.RecipientType == RecipientType.User && m.EncryptedContent == "Hello")), Times.Once); } [Test] public async Task SendMessageAsync_ToGroup_Success() { // Arrange var senderId = Guid.NewGuid(); var groupId = Guid.NewGuid(); var sendMessageParams = new SendMessage("Hello Group", null, groupId, RecipientType.Group, senderId, DateTime.UtcNow, new List()); _mockGroupsRepo.Setup(r => r.Exist(groupId)).Returns(true); _mockGroupsRepo.Setup(r => r.IsUserMemberOfGroupAsync(senderId, groupId)).ReturnsAsync(true); _mockMessagesRepo.Setup(r => r.AddAsync(It.IsAny())).Returns(Task.CompletedTask); // Act var result = await _messageService.SendMessageAsync(sendMessageParams); // Assert Assert.That(result, Is.Not.Null); Assert.That(result.IsSuccess, Is.True); Assert.That(result.Exception, Is.Null); _mockMessagesRepo.Verify(r => r.AddAsync(It.Is(m => m.RecipientId == groupId && m.RecipientType == RecipientType.Group)), Times.Once); } [Test] public async Task SendMessageAsync_ToUser_RecipientNotFound_ReturnsFailure() { // Arrange var senderId = Guid.NewGuid(); var recipientId = Guid.NewGuid(); var sendMessageParams = new SendMessage("Hello", null, recipientId, RecipientType.User, senderId, DateTime.UtcNow, new List()); _mockUsersRepo.Setup(r => r.ExistsByIdAsync(recipientId)).ReturnsAsync(false); // 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()); 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() ); _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()); Assert.That(result.Message, Is.Null); } // Test for EditMessageAsync action [Test] public async Task EditMessageAsync_Success() { // Arrange var editorId = Guid.NewGuid(); var messageId = Guid.NewGuid(); var originalMessage = new Message { Id = messageId, SenderId = editorId, EncryptedContent = "Old", RecipientId = Guid.NewGuid(), RecipientType = RecipientType.User }; var editParams = new EditMessage(editorId, messageId, "New Content", DateTime.UtcNow); _mockMessagesRepo.Setup(r => r.FindByIdAsync(messageId)).ReturnsAsync(originalMessage); _mockMessagesRepo.Setup(r => r.UpdateAsync(It.IsAny())).Returns(Task.CompletedTask); // Act var result = await _messageService.EditMessageAsync(editParams); // Assert Assert.That(result, Is.Not.Null); Assert.That(result.IsSuccess, Is.True); Assert.That(result.OriginalMessage, Is.Not.Null); Assert.That(messageId, Is.EqualTo(result.OriginalMessage!.Id)); _mockMessagesRepo.Verify(r => r.UpdateAsync(It.Is(m => m.Id == messageId && m.EncryptedContent == "New Content" && m.IsEdited == true && m.EditedAt == editParams.EditedAt)), Times.Once); } [Test] public async Task EditMessageAsync_MessageNotFound_ReturnsFailure() { // Arrange var editorId = Guid.NewGuid(); var messageId = Guid.NewGuid(); var editParams = new EditMessage(editorId, messageId, "New Content", DateTime.UtcNow); _mockMessagesRepo.Setup(r => r.FindByIdAsync(messageId)). ThrowsAsync(new NotFoundByKeyException(messageId)); // Act var result = await _messageService.EditMessageAsync(editParams); // 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>()); Assert.That(result.OriginalMessage, Is.Null); } [Test] public async Task EditMessageAsync_NotSender_ReturnsFailure() { // Arrange var editorId = Guid.NewGuid(); var senderId = Guid.NewGuid(); // Different from editorId var messageId = Guid.NewGuid(); var originalMessage = new Message { Id = messageId, SenderId = senderId, EncryptedContent = "Old" }; var editParams = new EditMessage(editorId, messageId, "New Content", DateTime.UtcNow); _mockMessagesRepo.Setup(r => r.FindByIdAsync(messageId)).ReturnsAsync(originalMessage); // Act var result = await _messageService.EditMessageAsync(editParams); // 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()); Assert.That(result.OriginalMessage, Is.Null); } // Test for DeleteMessageAsync action [Test] public async Task DeleteMessageAsync_Success() { // Arrange var deleterId = Guid.NewGuid(); var messageId = Guid.NewGuid(); var originalMessage = new Message { Id = messageId, SenderId = deleterId, RecipientId = Guid.NewGuid(), RecipientType = RecipientType.User }; var deleteParams = new DeleteMessage(deleterId, messageId); _mockMessagesRepo.Setup(r => r.FindByIdAsync(messageId)).ReturnsAsync(originalMessage); _mockMessagesRepo.Setup(r => r.RemoveAsync(messageId)).Returns(Task.CompletedTask); // Act var result = await _messageService.DeleteMessageAsync(deleteParams); // Assert Assert.That(result, Is.Not.Null); Assert.That(result.IsSuccess, Is.True); Assert.That(result.OriginalMessage, Is.Not.Null); Assert.That(messageId, Is.EqualTo(result.OriginalMessage!.Id)); _mockMessagesRepo.Verify(r => r.RemoveAsync(messageId), Times.Once); } [Test] public async Task DeleteMessageAsync_MessageNotFound_ReturnsFailure() { // Arrange var deleterId = Guid.NewGuid(); var messageId = Guid.NewGuid(); var deleteParams = new DeleteMessage(deleterId, messageId); _mockMessagesRepo.Setup(r => r.FindByIdAsync(messageId)). ThrowsAsync(new NotFoundByKeyException(messageId)); // Act var result = await _messageService.DeleteMessageAsync(deleteParams); // 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()); Assert.That(result.OriginalMessage, Is.Null); } [Test] public async Task DeleteMessageAsync_NotSender_ReturnsFailure() { // Arrange var deleterId = Guid.NewGuid(); var senderId = Guid.NewGuid(); // Different var messageId = Guid.NewGuid(); var originalMessage = new Message { Id = messageId, SenderId = senderId }; var deleteParams = new DeleteMessage(deleterId, messageId); _mockMessagesRepo.Setup(r => r.FindByIdAsync(messageId)).ReturnsAsync(originalMessage); // Act var result = await _messageService.DeleteMessageAsync(deleteParams); // 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()); Assert.That(result.OriginalMessage, Is.Null); } }