Перепиливание под чистый DDD
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||
<PackageReference Include="FluentAssertions" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
|
||||
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Modules\Admin\Knot.Modules.Admin.csproj" />
|
||||
<ProjectReference Include="..\..\src\Shared\Knot.Shared.Kernel\Knot.Shared.Kernel.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,58 @@
|
||||
using FluentAssertions;
|
||||
using Host.Application.Admin.Commands;
|
||||
using Knot.Modules.Auth.Application.Abstractions;
|
||||
using Knot.Modules.Auth.Domain;
|
||||
using Knot.Shared.Kernel;
|
||||
using NSubstitute;
|
||||
using Xunit;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Knot.Modules.Admin.UnitTests;
|
||||
|
||||
public class ResetUserPasswordCommandHandlerTests
|
||||
{
|
||||
private readonly IAuthUnitOfWork _authUnitOfWork;
|
||||
private readonly IUserRepository _userRepository;
|
||||
private readonly ResetUserPasswordCommandHandler _handler;
|
||||
|
||||
public ResetUserPasswordCommandHandlerTests()
|
||||
{
|
||||
_authUnitOfWork = Substitute.For<IAuthUnitOfWork>();
|
||||
_userRepository = Substitute.For<IUserRepository>();
|
||||
_handler = new ResetUserPasswordCommandHandler(_userRepository, _authUnitOfWork);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ShouldReturnError_WhenUserNotFound()
|
||||
{
|
||||
// Arrange
|
||||
var command = new ResetUserPasswordCommand(Guid.NewGuid(), "NewP@ssw0rd");
|
||||
_userRepository.GetByIdAsync(command.UserId, Arg.Any<CancellationToken>()).Returns((User?)null);
|
||||
|
||||
// Act
|
||||
var result = await _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
result.IsFailure.Should().BeTrue();
|
||||
result.Error.Should().Be(AuthErrors.UserNotFound);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ShouldSucceed_WhenUserFound()
|
||||
{
|
||||
// Arrange
|
||||
var user = User.Create("User", "pass", "salt", "admin");
|
||||
var command = new ResetUserPasswordCommand(user.Id, "NewP@ssw0rd");
|
||||
|
||||
_userRepository.GetByIdAsync(command.UserId, Arg.Any<CancellationToken>()).Returns(user);
|
||||
|
||||
// Act
|
||||
var result = await _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
result.IsSuccess.Should().BeTrue();
|
||||
await _authUnitOfWork.Received(1).SaveChangesAsync(Arg.Any<CancellationToken>());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.2">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||
<PackageReference Include="FluentAssertions" Version="8.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Modules\Identity\Knot.Modules.Auth.csproj" />
|
||||
<ProjectReference Include="..\..\src\Modules\Auth\Knot.Modules.Auth.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
using FluentAssertions;
|
||||
using NSubstitute;
|
||||
using Knot.Modules.Auth.Application.Abstractions;
|
||||
using Knot.Modules.Auth.Application.Users.Login;
|
||||
using Knot.Modules.Auth.Domain;
|
||||
using Knot.Shared.Kernel;
|
||||
using Knot.Modules.Auth.Application.Users.Auth;
|
||||
using Xunit;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Knot.Modules.Auth.UnitTests;
|
||||
|
||||
public class LoginUserCommandHandlerTests
|
||||
{
|
||||
private readonly IUserRepository _userRepository;
|
||||
private readonly IJwtTokenProvider _tokenProvider;
|
||||
private readonly LoginUserCommandHandler _handler;
|
||||
|
||||
public LoginUserCommandHandlerTests()
|
||||
{
|
||||
_userRepository = Substitute.For<IUserRepository>();
|
||||
_tokenProvider = Substitute.For<IJwtTokenProvider>();
|
||||
_handler = new LoginUserCommandHandler(_userRepository, _tokenProvider);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ShouldReturnToken_WhenCredentialsAreValid()
|
||||
{
|
||||
// Arrange
|
||||
var password = "password123";
|
||||
var passwordHash = BCrypt.Net.BCrypt.HashPassword(password);
|
||||
var user = User.Create("testuser", passwordHash, "Test User", null, null);
|
||||
|
||||
var command = new LoginUserCommand("testuser", password);
|
||||
|
||||
_userRepository.GetByUsernameAsync(command.Username, Arg.Any<CancellationToken>())
|
||||
.Returns(user);
|
||||
|
||||
_tokenProvider.Generate(user).Returns("valid-jwt-token");
|
||||
|
||||
// Act
|
||||
var result = await _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
result.IsSuccess.Should().BeTrue();
|
||||
result.Value.Token.Should().Be("valid-jwt-token");
|
||||
result.Value.User.Username.Should().Be("testuser");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ShouldReturnFailure_WhenUserDoesNotExist()
|
||||
{
|
||||
// Arrange
|
||||
var command = new LoginUserCommand("nonexistent", "password123");
|
||||
_userRepository.GetByUsernameAsync(command.Username, Arg.Any<CancellationToken>())
|
||||
.Returns((User)null!);
|
||||
|
||||
// Act
|
||||
var result = await _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
result.IsFailure.Should().BeTrue();
|
||||
result.Error.Code.Should().Be(AuthErrors.IdentityInvalidCredentials.Code);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ShouldReturnFailure_WhenPasswordIsInvalid()
|
||||
{
|
||||
// Arrange
|
||||
var correctPassword = "correctPassword";
|
||||
var passwordHash = BCrypt.Net.BCrypt.HashPassword(correctPassword);
|
||||
var user = User.Create("testuser", passwordHash, "Test User", null, null);
|
||||
|
||||
var command = new LoginUserCommand("testuser", "wrongPassword");
|
||||
|
||||
_userRepository.GetByUsernameAsync(command.Username, Arg.Any<CancellationToken>())
|
||||
.Returns(user);
|
||||
|
||||
// Act
|
||||
var result = await _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
result.IsFailure.Should().BeTrue();
|
||||
result.Error.Code.Should().Be(AuthErrors.IdentityInvalidCredentials.Code);
|
||||
}
|
||||
}
|
||||
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using FluentAssertions;
|
||||
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.Chats.Create;
|
||||
|
||||
namespace Knot.Modules.Conversations.UnitTests.Chats;
|
||||
|
||||
public class CreateChatCommandHandlerTests
|
||||
{
|
||||
private readonly IChatRepository _chatRepository;
|
||||
private readonly IChatsUnitOfWork _unitOfWork;
|
||||
private readonly CreateChatCommandHandler _handler;
|
||||
|
||||
public CreateChatCommandHandlerTests()
|
||||
{
|
||||
_chatRepository = Substitute.For<IChatRepository>();
|
||||
_unitOfWork = Substitute.For<IChatsUnitOfWork>();
|
||||
_handler = new CreateChatCommandHandler(_chatRepository, _unitOfWork);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ShouldCreateChatAndAddMembers()
|
||||
{
|
||||
// Arrange
|
||||
var request = new CreateChatCommand("Test Group", ChatType.Group, new List<Guid> { Guid.NewGuid(), Guid.NewGuid() });
|
||||
|
||||
// Act
|
||||
var result = await _handler.Handle(request, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
result.IsSuccess.Should().BeTrue();
|
||||
result.Value.Should().NotBeEmpty();
|
||||
|
||||
_chatRepository.Received(1).Add(Arg.Is<Chat>(c =>
|
||||
c.Name == "Test Group" &&
|
||||
c.Type == ChatType.Group &&
|
||||
c.Members.Count == 2 &&
|
||||
c.Members.First().Role == ChatRole.Owner &&
|
||||
c.Members.Last().Role == ChatRole.Member));
|
||||
|
||||
await _unitOfWork.Received(1).SaveChangesAsync(Arg.Any<CancellationToken>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using FluentAssertions;
|
||||
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.Chats.GetChats;
|
||||
using Knot.Modules.Conversations.Application.DTOs;
|
||||
|
||||
namespace Knot.Modules.Conversations.UnitTests.Chats;
|
||||
|
||||
public class GetChatsQueryHandlerTests
|
||||
{
|
||||
private readonly IChatRepository _chatRepository;
|
||||
private readonly IUserDisplayNameProvider _userProvider;
|
||||
private readonly IMessageRepository _messageRepository;
|
||||
private readonly IMessageReactionRepository _reactionRepository;
|
||||
private readonly GetChatsQueryHandler _handler;
|
||||
|
||||
public GetChatsQueryHandlerTests()
|
||||
{
|
||||
_chatRepository = Substitute.For<IChatRepository>();
|
||||
_userProvider = Substitute.For<IUserDisplayNameProvider>();
|
||||
_messageRepository = Substitute.For<IMessageRepository>();
|
||||
_reactionRepository = Substitute.For<IMessageReactionRepository>();
|
||||
|
||||
_handler = new GetChatsQueryHandler(_chatRepository, _userProvider, _messageRepository, _reactionRepository);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ShouldReturnUserChats_WhenTheyExist()
|
||||
{
|
||||
// Arrange
|
||||
var userId = Guid.NewGuid();
|
||||
var request = new GetChatsQuery(userId);
|
||||
|
||||
var chat1 = Chat.Create("Test Chat", ChatType.Group);
|
||||
chat1.GetType().GetProperty("Id")?.SetValue(chat1, Guid.NewGuid());
|
||||
chat1.AddMember(userId, ChatRole.Owner);
|
||||
|
||||
var chat2 = Chat.Create("Personal", ChatType.Personal);
|
||||
chat2.GetType().GetProperty("Id")?.SetValue(chat2, Guid.NewGuid());
|
||||
chat2.AddMember(userId, ChatRole.Member);
|
||||
|
||||
_chatRepository.GetUserChatsAsync(userId, Arg.Any<CancellationToken>())
|
||||
.Returns(new List<Chat> { chat1, chat2 });
|
||||
|
||||
_messageRepository.GetChatMessagesAsync(Arg.Any<Guid>(), 1, 0, Arg.Any<CancellationToken>())
|
||||
.Returns(new List<Message>());
|
||||
|
||||
_userProvider.GetUsersInfoAsync(Arg.Any<IEnumerable<Guid>>(), Arg.Any<CancellationToken>())
|
||||
.Returns(new Dictionary<Guid, UserInfo>());
|
||||
|
||||
// Act
|
||||
var result = await _handler.Handle(request, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
result.IsSuccess.Should().BeTrue();
|
||||
result.Value.Should().NotBeNull();
|
||||
|
||||
// It always appends synthetic "favorites" chat at the end if not found
|
||||
result.Value.Count.Should().Be(2);
|
||||
result.Value.Any(c => c.Name == "Test Chat").Should().BeTrue();
|
||||
result.Value.Any(c => c.Type == "favorites").Should().BeTrue();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
using FluentAssertions;
|
||||
using Knot.Modules.Conversations.Application.Chats.Commands.CreatePersonalChat;
|
||||
using Knot.Modules.Conversations.Domain;
|
||||
using Knot.Modules.Conversations.Application.Abstractions;
|
||||
using Knot.Shared.Kernel;
|
||||
using NSubstitute;
|
||||
using Xunit;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Knot.Modules.Conversations.UnitTests;
|
||||
|
||||
public class CreatePersonalChatCommandHandlerTests
|
||||
{
|
||||
private readonly IChatRepository _chatRepository;
|
||||
private readonly IChatsUnitOfWork _unitOfWork;
|
||||
private readonly CreatePersonalChatCommandHandler _handler;
|
||||
|
||||
public CreatePersonalChatCommandHandlerTests()
|
||||
{
|
||||
_chatRepository = Substitute.For<IChatRepository>();
|
||||
_unitOfWork = Substitute.For<IChatsUnitOfWork>();
|
||||
_handler = new CreatePersonalChatCommandHandler(_chatRepository, _unitOfWork);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ShouldReturnError_WhenChatAlreadyExists()
|
||||
{
|
||||
// Arrange
|
||||
var command = new CreatePersonalChatCommand(Guid.NewGuid(), Guid.NewGuid());
|
||||
_chatRepository.GetPersonalChatAsync(command.InitiatorId, command.TargetUserId, Arg.Any<CancellationToken>())
|
||||
.Returns(PersonalChat.Create(command.InitiatorId, command.TargetUserId));
|
||||
|
||||
// Act
|
||||
var result = await _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
result.IsFailure.Should().BeTrue();
|
||||
result.Error.Should().Be(ChatErrors.PersonalChatAlreadyExists);
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
using FluentAssertions;
|
||||
using NSubstitute;
|
||||
using Knot.Modules.Conversations.Application.Abstractions;
|
||||
using Knot.Modules.Conversations.Application.Chats.GetOrCreateFavorites;
|
||||
using Knot.Modules.Conversations.Domain;
|
||||
using Knot.Modules.Messaging.Domain;
|
||||
using Knot.Shared.Kernel;
|
||||
using Xunit;
|
||||
|
||||
namespace Knot.Modules.Conversations.UnitTests;
|
||||
|
||||
public class GetOrCreateFavoritesCommandHandlerTests
|
||||
{
|
||||
private readonly IChatRepository _chatRepository;
|
||||
private readonly IChatsUnitOfWork _unitOfWork;
|
||||
private readonly GetOrCreateFavoritesCommandHandler _handler;
|
||||
|
||||
public GetOrCreateFavoritesCommandHandlerTests()
|
||||
{
|
||||
_chatRepository = Substitute.For<IChatRepository>();
|
||||
_unitOfWork = Substitute.For<IChatsUnitOfWork>();
|
||||
_handler = new GetOrCreateFavoritesCommandHandler(_chatRepository, _unitOfWork);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ShouldReturnExistingChat_WhenFavoritesAlreadyExists()
|
||||
{
|
||||
// Arrange
|
||||
var userId = Guid.NewGuid();
|
||||
var existingChat = Chat.Create("Избранное", ChatType.Favorites);
|
||||
|
||||
_chatRepository.GetFavoritesAsync(userId, Arg.Any<CancellationToken>())
|
||||
.Returns(existingChat);
|
||||
|
||||
var command = new GetOrCreateFavoritesCommand(userId);
|
||||
|
||||
// Act
|
||||
var result = await _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
result.IsSuccess.Should().BeTrue();
|
||||
result.Value.Should().Be(existingChat.Id);
|
||||
|
||||
_chatRepository.DidNotReceive().Add(Arg.Any<Chat>());
|
||||
await _unitOfWork.DidNotReceive().SaveChangesAsync(Arg.Any<CancellationToken>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ShouldCreateNewChat_WhenFavoritesDoesNotExist()
|
||||
{
|
||||
// Arrange
|
||||
var userId = Guid.NewGuid();
|
||||
_chatRepository.GetFavoritesAsync(userId, Arg.Any<CancellationToken>())
|
||||
.Returns((Chat)null!);
|
||||
|
||||
var command = new GetOrCreateFavoritesCommand(userId);
|
||||
|
||||
// Act
|
||||
var result = await _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
result.IsSuccess.Should().BeTrue();
|
||||
result.Value.Should().NotBeEmpty();
|
||||
|
||||
_chatRepository.Received(1).Add(Arg.Is<Chat>(c =>
|
||||
c.Type == ChatType.Favorites &&
|
||||
c.Name == "Избранное" &&
|
||||
c.Members.Any(m => m.UserId == userId)));
|
||||
|
||||
await _unitOfWork.Received(1).SaveChangesAsync(Arg.Any<CancellationToken>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.2">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||
<PackageReference Include="FluentAssertions" Version="8.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Modules\Chats\Knot.Modules.Conversations.csproj" />
|
||||
<ProjectReference Include="..\..\src\Modules\Messaging\Knot.Modules.Messaging.csproj" />
|
||||
<ProjectReference Include="..\..\src\Modules\Conversations\Knot.Modules.Conversations.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
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;
|
||||
|
||||
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 SendMessageCommandHandler _handler;
|
||||
|
||||
public SendMessageCommandHandlerTests()
|
||||
{
|
||||
_chatRepository = Substitute.For<IChatRepository>();
|
||||
_messageRepository = Substitute.For<IMessageRepository>();
|
||||
_unitOfWork = Substitute.For<IChatsUnitOfWork>();
|
||||
_mediator = Substitute.For<IMediator>();
|
||||
|
||||
_handler = new SendMessageCommandHandler(_chatRepository, _messageRepository, _unitOfWork, _mediator);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ShouldReturnFailure_WhenChatNotFound()
|
||||
{
|
||||
// Arrange
|
||||
var command = new SendMessageCommand(Guid.NewGuid(), Guid.NewGuid(), "Hello", "text");
|
||||
_chatRepository.GetByIdAsync(command.ChatId, Arg.Any<CancellationToken>())
|
||||
.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<CancellationToken>())
|
||||
.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<CancellationToken>())
|
||||
.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<Message>(m =>
|
||||
m.ChatId == chat.Id &&
|
||||
m.SenderId == senderId &&
|
||||
m.Content == "Hello" &&
|
||||
m.Type == "text"));
|
||||
|
||||
await _unitOfWork.Received(1).SaveChangesAsync(Arg.Any<CancellationToken>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||
<PackageReference Include="FluentAssertions" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
|
||||
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Modules\Federation\Knot.Modules.Federation.csproj" />
|
||||
<ProjectReference Include="..\..\src\Shared\Knot.Shared.Kernel\Knot.Shared.Kernel.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,28 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||
<PackageReference Include="FluentAssertions" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
|
||||
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Modules\Klipy\Knot.Modules.Klipy.csproj" />
|
||||
<ProjectReference Include="..\..\src\Shared\Knot.Shared.Kernel\Knot.Shared.Kernel.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
|
||||
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
|
||||
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,41 @@
|
||||
using FluentAssertions;
|
||||
using Knot.Modules.Profiles.Application.Profiles.Commands.UpdateProfile;
|
||||
using Knot.Modules.Profiles.Domain;
|
||||
using Knot.Modules.Profiles.Application.Abstractions;
|
||||
using Knot.Shared.Kernel;
|
||||
using NSubstitute;
|
||||
using Xunit;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Knot.Modules.Profiles.UnitTests;
|
||||
|
||||
public class UpdateProfileCommandHandlerTests
|
||||
{
|
||||
private readonly IProfileRepository _profileRepository;
|
||||
private readonly IProfilesUnitOfWork _unitOfWork;
|
||||
private readonly UpdateProfileCommandHandler _handler;
|
||||
|
||||
public UpdateProfileCommandHandlerTests()
|
||||
{
|
||||
_profileRepository = Substitute.For<IProfileRepository>();
|
||||
_unitOfWork = Substitute.For<IProfilesUnitOfWork>();
|
||||
_handler = new UpdateProfileCommandHandler(_profileRepository, _unitOfWork);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ShouldReturnError_WhenProfileNotFound()
|
||||
{
|
||||
// Arrange
|
||||
var command = new UpdateProfileCommand(Guid.NewGuid(), "FirstName", "LastName", "Bio");
|
||||
_profileRepository.GetByIdAsync(command.UserId, Arg.Any<CancellationToken>()).Returns((UserProfile?)null);
|
||||
|
||||
// Act
|
||||
var result = await _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
result.IsFailure.Should().BeTrue();
|
||||
result.Error.Should().Be(ProfileErrors.NotFound);
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||
<PackageReference Include="FluentAssertions" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
|
||||
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Modules\Relations\Knot.Modules.Relations.csproj" />
|
||||
<ProjectReference Include="..\..\src\Shared\Knot.Shared.Kernel\Knot.Shared.Kernel.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Knot.Modules.Relations.UnitTests;
|
||||
|
||||
public class UnitTest1
|
||||
{
|
||||
[Fact]
|
||||
public void Test1()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||
<PackageReference Include="FluentAssertions" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
|
||||
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Modules\Settings\Knot.Modules.Settings.csproj" />
|
||||
<ProjectReference Include="..\..\src\Shared\Knot.Shared.Kernel\Knot.Shared.Kernel.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Knot.Modules.Settings.UnitTests;
|
||||
|
||||
public class UnitTest1
|
||||
{
|
||||
[Fact]
|
||||
public void Test1()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||
<PackageReference Include="FluentAssertions" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
|
||||
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Modules\Storage\Knot.Modules.Storage.csproj" />
|
||||
<ProjectReference Include="..\..\src\Shared\Knot.Shared.Kernel\Knot.Shared.Kernel.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Knot.Modules.Storage.UnitTests;
|
||||
|
||||
public class UnitTest1
|
||||
{
|
||||
[Fact]
|
||||
public void Test1()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||
<PackageReference Include="FluentAssertions" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
|
||||
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Modules\Stories\Knot.Modules.Stories.csproj" />
|
||||
<ProjectReference Include="..\..\src\Shared\Knot.Shared.Kernel\Knot.Shared.Kernel.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Knot.Modules.Stories.UnitTests;
|
||||
|
||||
public class UnitTest1
|
||||
{
|
||||
[Fact]
|
||||
public void Test1()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||
<PackageReference Include="FluentAssertions" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
|
||||
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Modules\TelegramImport\Knot.Modules.TelegramImport.csproj" />
|
||||
<ProjectReference Include="..\..\src\Shared\Knot.Shared.Kernel\Knot.Shared.Kernel.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Knot.Modules.TelegramImport.UnitTests;
|
||||
|
||||
public class UnitTest1
|
||||
{
|
||||
[Fact]
|
||||
public void Test1()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||
<PackageReference Include="FluentAssertions" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
|
||||
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Modules\WebRtc\Knot.Modules.WebRtc.csproj" />
|
||||
<ProjectReference Include="..\..\src\Shared\Knot.Shared.Kernel\Knot.Shared.Kernel.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Knot.Modules.WebRtc.UnitTests;
|
||||
|
||||
public class UnitTest1
|
||||
{
|
||||
[Fact]
|
||||
public void Test1()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user