Перепиливание под чистый DDD

This commit is contained in:
Халимов Рустам
2026-03-22 23:59:33 +03:00
parent 5da1a2f45d
commit 6e532b021d
302 changed files with 3595 additions and 3679 deletions
@@ -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);
}
}
@@ -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();
}
}
@@ -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);
}
}
@@ -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>());
}
}
@@ -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>
@@ -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>());
}
}
@@ -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>
@@ -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);
}
}
@@ -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()
{
}
}
@@ -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()
{
}
}