using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using FluentAssertions; using MediatR; using NSubstitute; using Xunit; using Knot.Shared.Kernel; using Knot.Modules.Conversations.Domain; using Knot.Modules.Messaging.Domain; using Knot.Modules.Conversations.Application.Abstractions; using Knot.Modules.Conversations.Application.Messages.Send; using Knot.Modules.Settings.Application.Settings.Abstractions; using Knot.Modules.Settings.Application.Settings.DTOs; namespace Knot.Modules.Conversations.UnitTests.Messages; public class SendMessageCommandHandlerTests { private readonly IChatRepository _chatRepository; private readonly IMessageRepository _messageRepository; private readonly IChatsUnitOfWork _unitOfWork; private readonly IMediator _mediator; private readonly IMessagesSettings _messagesSettings; private readonly SendMessageCommandHandler _handler; public SendMessageCommandHandlerTests() { _chatRepository = Substitute.For(); _messageRepository = Substitute.For(); _unitOfWork = Substitute.For(); _mediator = Substitute.For(); _messagesSettings = Substitute.For(); var config = new Knot.Modules.Settings.Application.Settings.DTOs.MessagesConfig(); _messagesSettings.Current.Returns(config); _handler = new SendMessageCommandHandler(_chatRepository, _messageRepository, _unitOfWork, _mediator, _messagesSettings); } [Fact] public async Task Handle_ShouldReturnFailure_WhenChatNotFound() { // Arrange var command = new SendMessageCommand(Guid.NewGuid(), Guid.NewGuid(), "Hello", "text"); _chatRepository.GetByIdAsync(command.ChatId, Arg.Any()) .Returns((Chat)null!); // Act var result = await _handler.Handle(command, CancellationToken.None); // Assert result.IsFailure.Should().BeTrue(); result.Error.Code.Should().Be(ChatErrors.ChatsNotFound.Code); } [Fact] public async Task Handle_ShouldReturnFailure_WhenSenderIsNotMember() { // Arrange var chat = Chat.Create("Test", ChatType.Group); var command = new SendMessageCommand(chat.Id, Guid.NewGuid(), "Hello", "text"); _chatRepository.GetByIdAsync(command.ChatId, Arg.Any()) .Returns(chat); // Act var result = await _handler.Handle(command, CancellationToken.None); // Assert result.IsFailure.Should().BeTrue(); result.Error.Code.Should().Be(ChatErrors.ChatsForbidden.Code); } [Fact] public async Task Handle_ShouldCreateMessage_WhenAuthorized() { // Arrange var senderId = Guid.NewGuid(); var chat = Chat.Create("Test", ChatType.Group); chat.AddMember(senderId, ChatRole.Member); var command = new SendMessageCommand(chat.Id, senderId, "Hello", "text"); _chatRepository.GetByIdAsync(command.ChatId, Arg.Any()) .Returns(chat); // Act var result = await _handler.Handle(command, CancellationToken.None); // Assert result.IsSuccess.Should().BeTrue(); result.Value.Should().NotBeEmpty(); _messageRepository.Received(1).Add(Arg.Is(m => m.ChatId == chat.Id && m.SenderId == senderId && m.Content == "Hello" && m.Type == "text")); await _unitOfWork.Received(1).SaveChangesAsync(Arg.Any()); } }