diff --git a/src/Voltiq.API/Controllers/BaseApiController.cs b/src/Voltiq.API/Controllers/BaseApiController.cs index d2b1f43..e02d5fc 100644 --- a/src/Voltiq.API/Controllers/BaseApiController.cs +++ b/src/Voltiq.API/Controllers/BaseApiController.cs @@ -8,6 +8,7 @@ namespace Voltiq.API.Controllers; [ApiController] +[Produces("application/json", "application/problem+json")] [Route("api/v{version:apiVersion}/[controller]")] public abstract class BaseApiController : ControllerBase { diff --git a/src/Voltiq.API/Controllers/Materials/MaterialsController.cs b/src/Voltiq.API/Controllers/Materials/MaterialsController.cs index 47ea358..56db17f 100644 --- a/src/Voltiq.API/Controllers/Materials/MaterialsController.cs +++ b/src/Voltiq.API/Controllers/Materials/MaterialsController.cs @@ -11,7 +11,6 @@ namespace Voltiq.API.Controllers.Materials; [ApiVersion("1.0")] -[Route("api/v{version:apiVersion}/materials")] public sealed class MaterialsController : BaseApiController { /// Registers a new material for the authenticated user. diff --git a/src/Voltiq.API/ExceptionHandlers/UnauthorizedExceptionHandler.cs b/src/Voltiq.API/ExceptionHandlers/UnauthorizedExceptionHandler.cs deleted file mode 100644 index 40dc39c..0000000 --- a/src/Voltiq.API/ExceptionHandlers/UnauthorizedExceptionHandler.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Microsoft.AspNetCore.Diagnostics; -using Voltiq.Exceptions.Resources; - -// TODO: Remove this handler -namespace Voltiq.API.ExceptionHandlers; - -internal sealed class UnauthorizedExceptionHandler(IHostEnvironment env) : IExceptionHandler -{ - public async ValueTask TryHandleAsync( - HttpContext httpContext, - Exception exception, - CancellationToken cancellationToken) - { - if (exception is not UnauthorizedAccessException) - return false; - - var response = new - { - title = ResourceErrorMessages.TITULO_NAO_AUTORIZADO, - status = StatusCodes.Status401Unauthorized, - instance = httpContext.Request.Path.Value, - traceId = env.IsDevelopment() ? httpContext.TraceIdentifier : null, - }; - - httpContext.Response.StatusCode = StatusCodes.Status401Unauthorized; - httpContext.Response.ContentType = "application/problem+json"; - - await httpContext.Response.WriteAsJsonAsync(response, cancellationToken); - - return true; - } -} diff --git a/src/Voltiq.API/Voltiq.API.csproj b/src/Voltiq.API/Voltiq.API.csproj index 80b46c0..bcbe7ed 100644 --- a/src/Voltiq.API/Voltiq.API.csproj +++ b/src/Voltiq.API/Voltiq.API.csproj @@ -1,40 +1,39 @@  - - - + + + - - - - + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - - - + + + - - + - + - + - + @@ -42,7 +41,7 @@ enable enable true - 0cd97f61-50df-4c03-8e90-8348a3369961 - + 0cd97f61-50df-4c03-8e90-8348a3369961 + diff --git a/tests/Voltiq.CommonTestUtilities/Builders/TestDataBuilder.cs b/tests/Voltiq.CommonTestUtilities/Builders/TestDataBuilder.cs new file mode 100644 index 0000000..cb42995 --- /dev/null +++ b/tests/Voltiq.CommonTestUtilities/Builders/TestDataBuilder.cs @@ -0,0 +1,126 @@ +using Voltiq.Domain.Entities; +using Voltiq.Domain.Enums; +using Voltiq.Domain.Interfaces; +using Voltiq.Domain.Interfaces.Repositories.Budget; +using Voltiq.Domain.Interfaces.Repositories.Client; +using Voltiq.Domain.Interfaces.Repositories.Material; +using Voltiq.Domain.Interfaces.Repositories.RefreshToken; +using Voltiq.Domain.Interfaces.Repositories.User; +using Voltiq.Domain.ValueObjects; + +namespace Voltiq.CommonTestUtilities.Builders; + +public static class TestDataBuilder +{ + private static CancellationToken Ct => TestContext.Current.CancellationToken; + + public static User MakeUser( + string name = "João Silva", + string email = "joao@example.com", + string document = "529.982.247-25", + string passwordHash = "$argon2id$hash") + { + var emailVo = Email.Create(email).Value; + var documentVo = Document.Create(document).Value; + return User.Register(name, emailVo, documentVo, passwordHash); + } + + public static Client MakeClient( + Guid userId, + string name = "Cliente Teste", + string email = "cliente@example.com", + string phone = "(11) 99999-9999") + { + var emailVo = Email.Create(email).Value; + return Client.Register(userId, name, phone, emailVo, + Address.Create("Rua das Flores", "123", "São Paulo", "SP", "01310-100")); + } + + public static Material MakeMaterial( + Guid userId, + string name = "Cabo 10mm", + decimal defaultPrice = 15.50m, + MaterialUnit unit = MaterialUnit.Metro) + { + return Material.Register(userId, name, defaultPrice, unit); + } + + public static Budget MakeBudget(Guid userId, Guid clientId) + { + return Budget.Register(userId, clientId); + } + + public static RefreshToken MakeRefreshToken( + string token, + Guid userId, + int daysToExpire = 7) + { + return RefreshToken.Create(token, userId, daysToExpire); + } + + + public static async Task SeedUserAsync( + IUserWriteOnlyRepository repository, + IUnitOfWork unitOfWork, + string name = "João Silva", + string email = "joao@example.com", + string document = "529.982.247-25") + { + var user = MakeUser(name, email, document); + await repository.AddAsync(user, Ct); + await unitOfWork.SaveChangesAsync(Ct); + return user; + } + + public static async Task SeedClientAsync( + IClientWriteOnlyRepository repository, + IUnitOfWork unitOfWork, + Guid userId, + string name = "Cliente Teste", + string email = "cliente@example.com") + { + var client = MakeClient(userId, name, email); + await repository.AddAsync(client, Ct); + await unitOfWork.SaveChangesAsync(Ct); + return client; + } + + public static async Task SeedMaterialAsync( + IMaterialWriteOnlyRepository repository, + IUnitOfWork unitOfWork, + Guid userId, + string name = "Cabo 10mm", + decimal defaultPrice = 15.50m, + MaterialUnit unit = MaterialUnit.Metro) + { + var material = MakeMaterial(userId, name, defaultPrice, unit); + await repository.AddAsync(material, Ct); + await unitOfWork.SaveChangesAsync(Ct); + return material; + } + + public static async Task SeedBudgetAsync( + IBudgetWriteOnlyRepository repository, + IUnitOfWork unitOfWork, + Guid userId, + Guid clientId) + { + var budget = MakeBudget(userId, clientId); + await repository.AddAsync(budget, Ct); + await unitOfWork.SaveChangesAsync(Ct); + return budget; + } + + public static async Task SeedRefreshTokenAsync( + IRefreshTokenWriteOnlyRepository repository, + IUnitOfWork unitOfWork, + Guid userId, + string token = "test-token", + int daysToExpire = 7) + { + var refreshToken = MakeRefreshToken(token, userId, daysToExpire); + await repository.AddAsync(refreshToken, Ct); + await unitOfWork.SaveChangesAsync(Ct); + return refreshToken; + } +} diff --git a/tests/Voltiq.CommonTestUtilities/Fixtures/PostgreSqlContainerFixture.cs b/tests/Voltiq.CommonTestUtilities/Fixtures/PostgreSqlContainerFixture.cs index 3e38395..f500445 100644 --- a/tests/Voltiq.CommonTestUtilities/Fixtures/PostgreSqlContainerFixture.cs +++ b/tests/Voltiq.CommonTestUtilities/Fixtures/PostgreSqlContainerFixture.cs @@ -8,5 +8,5 @@ public sealed class PostgreSqlContainerFixture(IMessageSink messageSink) : ContainerFixture(messageSink) { protected override PostgreSqlBuilder Configure() - => new PostgreSqlBuilder("postgres:16-alpine"); + => new PostgreSqlBuilder("postgres:17-alpine"); } diff --git a/tests/Voltiq.Infrastructure.Tests/Persistence/BudgetRepositoryTests.cs b/tests/Voltiq.Infrastructure.Tests/Persistence/BudgetRepositoryTests.cs index 9c1220a..a1f95a3 100644 --- a/tests/Voltiq.Infrastructure.Tests/Persistence/BudgetRepositoryTests.cs +++ b/tests/Voltiq.Infrastructure.Tests/Persistence/BudgetRepositoryTests.cs @@ -1,13 +1,13 @@ using Microsoft.EntityFrameworkCore; using Shouldly; +using Voltiq.CommonTestUtilities.Builders; using Voltiq.CommonTestUtilities.Database; using Voltiq.CommonTestUtilities.Fixtures; using Voltiq.Domain.Entities; using Voltiq.Domain.Enums; -using Voltiq.Domain.ValueObjects; +using Voltiq.Domain.Interfaces.Repositories.Budget; using Voltiq.Infrastructure.Persistence; using Voltiq.Infrastructure.Persistence.Repositories; -using Voltiq.Domain.Interfaces.Repositories.Budget; using Voltiq.Infrastructure.Persistence.Repositories.Budget; using Voltiq.Infrastructure.Persistence.Repositories.Client; using Voltiq.Infrastructure.Persistence.Repositories.User; @@ -18,9 +18,9 @@ public class BudgetRepositoryTests(PostgreSqlContainerFixture fixture) : IClassFixture, IAsyncLifetime { private static readonly Guid UserId = Guid.NewGuid(); + private IBudgetReadOnlyRepository _budgetReadOnly = null!; private BudgetRepository _budgetRepository = null!; - private IBudgetReadOnlyRepository _budgetReadOnly = null!; private ClientRepository _clientRepository = null!; private ApplicationDbContext _dbContext = null!; private UnitOfWork _unitOfWork = null!; @@ -45,51 +45,14 @@ public async ValueTask DisposeAsync() await _dbContext.DisposeAsync(); } - private static User MakeUser(string email = "joao@example.com", string doc = "529.982.247-25") - { - var userEmail = Email.Create(email).Value; - var userDocument = Document.Create(doc).Value; - return User.Register("João Silva", userEmail, userDocument, "$argon2id$hash"); - } - - private static Client MakeClient(Guid userId, string email = "cliente@example.com") - { - var clientEmail = Email.Create(email).Value; - return Client.Register(userId, "Cliente Teste", "(11) 99999-9999", clientEmail, - Address.Create("Rua das Flores", "123", "São Paulo", "SP", "01310-100")); - } - - private static Budget MakeBudget(Guid userId, Guid clientId) - { - return Budget.Register(userId, clientId); - } - - private async Task CreateAndSaveUserAsync(string email = "joao@example.com", - string doc = "529.982.247-25") - { - var user = MakeUser(email, doc); - await _userRepository.AddAsync(user); - await _unitOfWork.SaveChangesAsync(); - return user; - } - - private async Task CreateAndSaveClientAsync(Guid userId) - { - var client = MakeClient(userId); - await _clientRepository.AddAsync(client); - await _unitOfWork.SaveChangesAsync(); - return client; - } - [Fact] public async Task AddAndGetById_ShouldPersistBudget() { - var user = await CreateAndSaveUserAsync(); - var client = await CreateAndSaveClientAsync(user.Id); - var budget = MakeBudget(user.Id, client.Id); - - await _budgetRepository.AddAsync(budget, TestContext.Current.CancellationToken); - await _unitOfWork.SaveChangesAsync(TestContext.Current.CancellationToken); + var user = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork); + var client = await TestDataBuilder.SeedClientAsync(_clientRepository, _unitOfWork, user.Id); + var budget = + await TestDataBuilder.SeedBudgetAsync(_budgetRepository, _unitOfWork, user.Id, + client.Id); var found = await _budgetRepository.GetByIdAsync(budget.Id, TestContext.Current.CancellationToken); @@ -105,19 +68,19 @@ public async Task AddAndGetById_ShouldPersistBudget() [Fact] public async Task GetByUserIdAsync_ShouldReturnOnlyBudgetsOfUser() { - var user1 = await CreateAndSaveUserAsync(); - var user2 = await CreateAndSaveUserAsync("maria@example.com", "11222333000181"); + var user1 = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork); + var user2 = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork, + email: "maria@example.com", document: "11222333000181"); - var client1 = await CreateAndSaveClientAsync(user1.Id); - var client2 = await CreateAndSaveClientAsync(user2.Id); + var client1 = + await TestDataBuilder.SeedClientAsync(_clientRepository, _unitOfWork, user1.Id); + var client2 = await TestDataBuilder.SeedClientAsync(_clientRepository, _unitOfWork, + user2.Id, + email: "cliente2@example.com"); - await _budgetRepository.AddAsync(MakeBudget(user1.Id, client1.Id), - TestContext.Current.CancellationToken); - await _budgetRepository.AddAsync(MakeBudget(user1.Id, client1.Id), - TestContext.Current.CancellationToken); - await _budgetRepository.AddAsync(MakeBudget(user2.Id, client2.Id), - TestContext.Current.CancellationToken); - await _unitOfWork.SaveChangesAsync(TestContext.Current.CancellationToken); + await TestDataBuilder.SeedBudgetAsync(_budgetRepository, _unitOfWork, user1.Id, client1.Id); + await TestDataBuilder.SeedBudgetAsync(_budgetRepository, _unitOfWork, user1.Id, client1.Id); + await TestDataBuilder.SeedBudgetAsync(_budgetRepository, _unitOfWork, user2.Id, client2.Id); var user1Budgets = await _budgetRepository.GetByUserIdAsync(user1.Id, @@ -130,12 +93,11 @@ await _budgetRepository.GetByUserIdAsync(user1.Id, [Fact] public async Task GetByIdAndUserIdAsync_ShouldReturnBudget_WhenBelongsToUser() { - var user = await CreateAndSaveUserAsync(); - var client = await CreateAndSaveClientAsync(user.Id); - var budget = MakeBudget(user.Id, client.Id); - - await _budgetRepository.AddAsync(budget, TestContext.Current.CancellationToken); - await _unitOfWork.SaveChangesAsync(TestContext.Current.CancellationToken); + var user = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork); + var client = await TestDataBuilder.SeedClientAsync(_clientRepository, _unitOfWork, user.Id); + var budget = + await TestDataBuilder.SeedBudgetAsync(_budgetRepository, _unitOfWork, user.Id, + client.Id); var found = await _budgetReadOnly.GetByIdAndUserIdAsync(budget.Id, user.Id, TestContext.Current.CancellationToken); @@ -147,14 +109,15 @@ public async Task GetByIdAndUserIdAsync_ShouldReturnBudget_WhenBelongsToUser() [Fact] public async Task GetByIdAndUserIdAsync_ShouldReturnNull_WhenBudgetBelongsToAnotherUser() { - var user1 = await CreateAndSaveUserAsync(); - var user2 = await CreateAndSaveUserAsync("outro@example.com", "11222333000181"); + var user1 = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork); + var user2 = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork, + email: "outro@example.com", document: "11222333000181"); - var client1 = await CreateAndSaveClientAsync(user1.Id); - var budget = MakeBudget(user1.Id, client1.Id); - - await _budgetRepository.AddAsync(budget, TestContext.Current.CancellationToken); - await _unitOfWork.SaveChangesAsync(TestContext.Current.CancellationToken); + var client1 = + await TestDataBuilder.SeedClientAsync(_clientRepository, _unitOfWork, user1.Id); + var budget = + await TestDataBuilder.SeedBudgetAsync(_budgetRepository, _unitOfWork, user1.Id, + client1.Id); var found = await _budgetReadOnly.GetByIdAndUserIdAsync(budget.Id, user2.Id, TestContext.Current.CancellationToken); @@ -165,12 +128,12 @@ public async Task GetByIdAndUserIdAsync_ShouldReturnNull_WhenBudgetBelongsToAnot [Fact] public async Task GetByIdWithItemsAndUserIdAsync_ShouldReturnBudgetWithItems() { - var user = await CreateAndSaveUserAsync(); - var client = await CreateAndSaveClientAsync(user.Id); - var budget = MakeBudget(user.Id, client.Id); + var user = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork); + var client = await TestDataBuilder.SeedClientAsync(_clientRepository, _unitOfWork, user.Id); + + var budget = TestDataBuilder.MakeBudget(user.Id, client.Id); var item = BudgetItem.Create(budget.Id, null, "Cabo 10mm", MaterialUnit.Metro, 2, 15.50m); budget.AddItem(item); - await _budgetRepository.AddAsync(budget, TestContext.Current.CancellationToken); await _unitOfWork.SaveChangesAsync(TestContext.Current.CancellationToken); @@ -185,13 +148,14 @@ public async Task GetByIdWithItemsAndUserIdAsync_ShouldReturnBudgetWithItems() [Fact] public async Task GetByIdWithItemsAndUserIdAsync_ShouldReturnNull_WhenBelongsToAnotherUser() { - var user1 = await CreateAndSaveUserAsync(); - var user2 = await CreateAndSaveUserAsync("outro@example.com", "11222333000181"); - var client1 = await CreateAndSaveClientAsync(user1.Id); - var budget = MakeBudget(user1.Id, client1.Id); - - await _budgetRepository.AddAsync(budget, TestContext.Current.CancellationToken); - await _unitOfWork.SaveChangesAsync(TestContext.Current.CancellationToken); + var user1 = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork); + var user2 = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork, + email: "outro@example.com", document: "11222333000181"); + var client1 = + await TestDataBuilder.SeedClientAsync(_clientRepository, _unitOfWork, user1.Id); + var budget = + await TestDataBuilder.SeedBudgetAsync(_budgetRepository, _unitOfWork, user1.Id, + client1.Id); var found = await _budgetReadOnly.GetByIdWithItemsAndUserIdAsync(budget.Id, user2.Id, TestContext.Current.CancellationToken); diff --git a/tests/Voltiq.Infrastructure.Tests/Persistence/ClientRepositoryTests.cs b/tests/Voltiq.Infrastructure.Tests/Persistence/ClientRepositoryTests.cs index c097f6f..71da220 100644 --- a/tests/Voltiq.Infrastructure.Tests/Persistence/ClientRepositoryTests.cs +++ b/tests/Voltiq.Infrastructure.Tests/Persistence/ClientRepositoryTests.cs @@ -1,8 +1,8 @@ using Microsoft.EntityFrameworkCore; using Shouldly; +using Voltiq.CommonTestUtilities.Builders; using Voltiq.CommonTestUtilities.Database; using Voltiq.CommonTestUtilities.Fixtures; -using Voltiq.Domain.Entities; using Voltiq.Domain.ValueObjects; using Voltiq.Infrastructure.Persistence; using Voltiq.Infrastructure.Persistence.Repositories; @@ -42,37 +42,11 @@ public async ValueTask DisposeAsync() await _dbContext.DisposeAsync(); } - private static User MakeUser() - { - var email = Email.Create("joao@example.com").Value; - var document = Document.Create("529.982.247-25").Value; - return User.Register("João Silva", email, document, "$argon2id$hash"); - } - - private static Client MakeClient(Guid userId, string name = "Cliente Teste", - string email = "cliente@example.com") - { - var emailVo = Email.Create(email).Value; - return Client.Register(userId, name, "(11) 99999-9999", emailVo, - Address.Create("Rua das Flores", "123", "São Paulo", "SP", "01310-100")); - } - - private async Task CreateAndSaveUserAsync() - { - var user = MakeUser(); - await _userRepository.AddAsync(user); - await _unitOfWork.SaveChangesAsync(); - return user; - } - [Fact] public async Task AddAndGetById_ShouldPersistClient() { - var user = await CreateAndSaveUserAsync(); - var client = MakeClient(user.Id); - - await _clientRepository.AddAsync(client, TestContext.Current.CancellationToken); - await _unitOfWork.SaveChangesAsync(TestContext.Current.CancellationToken); + var user = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork); + var client = await TestDataBuilder.SeedClientAsync(_clientRepository, _unitOfWork, user.Id); var found = await _clientReadOnly.GetByIdAndUserIdAsync(client.Id, user.Id, TestContext.Current.CancellationToken); @@ -90,22 +64,16 @@ public async Task AddAndGetById_ShouldPersistClient() [Fact] public async Task GetByUserIdAsync_ShouldReturnOnlyClientsOfUser() { - var user1 = await CreateAndSaveUserAsync(); - - var email2 = Email.Create("maria@example.com").Value; - var doc2 = Document.Create("11222333000181").Value; - var user2 = User.Register("Maria Santos", email2, doc2, "$argon2id$hash2"); - await _userRepository.AddAsync(user2, TestContext.Current.CancellationToken); - await _unitOfWork.SaveChangesAsync(TestContext.Current.CancellationToken); - - var client1 = MakeClient(user1.Id, "Cliente User1", "user1a@example.com"); - var client2 = MakeClient(user1.Id, "Cliente User1 B", "user1b@example.com"); - var client3 = MakeClient(user2.Id, "Cliente User2", "user2@example.com"); + var user1 = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork); + var user2 = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork, + name: "Maria Santos", email: "maria@example.com", document: "11222333000181"); - await _clientRepository.AddAsync(client1, TestContext.Current.CancellationToken); - await _clientRepository.AddAsync(client2, TestContext.Current.CancellationToken); - await _clientRepository.AddAsync(client3, TestContext.Current.CancellationToken); - await _unitOfWork.SaveChangesAsync(TestContext.Current.CancellationToken); + await TestDataBuilder.SeedClientAsync(_clientRepository, _unitOfWork, user1.Id, + name: "Cliente User1", email: "user1a@example.com"); + await TestDataBuilder.SeedClientAsync(_clientRepository, _unitOfWork, user1.Id, + name: "Cliente User1 B", email: "user1b@example.com"); + await TestDataBuilder.SeedClientAsync(_clientRepository, _unitOfWork, user2.Id, + name: "Cliente User2", email: "user2@example.com"); var user1Clients = await _clientRepository.GetByUserIdAsync(user1.Id, @@ -118,11 +86,8 @@ await _clientRepository.GetByUserIdAsync(user1.Id, [Fact] public async Task GetByIdAndUserIdAsync_ShouldReturnClient_WhenBelongsToUser() { - var user = await CreateAndSaveUserAsync(); - var client = MakeClient(user.Id); - - await _clientRepository.AddAsync(client, TestContext.Current.CancellationToken); - await _unitOfWork.SaveChangesAsync(TestContext.Current.CancellationToken); + var user = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork); + var client = await TestDataBuilder.SeedClientAsync(_clientRepository, _unitOfWork, user.Id); var found = await _clientReadOnly.GetByIdAndUserIdAsync(client.Id, user.Id, TestContext.Current.CancellationToken); @@ -134,17 +99,11 @@ public async Task GetByIdAndUserIdAsync_ShouldReturnClient_WhenBelongsToUser() [Fact] public async Task GetByIdAndUserIdAsync_ShouldReturnNull_WhenClientBelongsToAnotherUser() { - var user1 = await CreateAndSaveUserAsync(); - - var email2 = Email.Create("outro@example.com").Value; - var doc2 = Document.Create("11222333000181").Value; - var user2 = User.Register("Outro User", email2, doc2, "$argon2id$hash2"); - await _userRepository.AddAsync(user2, TestContext.Current.CancellationToken); - await _unitOfWork.SaveChangesAsync(TestContext.Current.CancellationToken); + var user1 = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork); + var user2 = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork, + name: "Outro User", email: "outro@example.com", document: "11222333000181"); - var client = MakeClient(user1.Id); - await _clientRepository.AddAsync(client, TestContext.Current.CancellationToken); - await _unitOfWork.SaveChangesAsync(TestContext.Current.CancellationToken); + var client = await TestDataBuilder.SeedClientAsync(_clientRepository, _unitOfWork, user1.Id); var found = await _clientReadOnly.GetByIdAndUserIdAsync(client.Id, user2.Id, TestContext.Current.CancellationToken); @@ -155,10 +114,9 @@ public async Task GetByIdAndUserIdAsync_ShouldReturnNull_WhenClientBelongsToAnot [Fact] public async Task ExistsWithEmailForUserAsync_ShouldReturnTrue_WhenEmailExistsForUser() { - var user = await CreateAndSaveUserAsync(); - var client = MakeClient(user.Id, email: "ocupado@example.com"); - await _clientRepository.AddAsync(client, TestContext.Current.CancellationToken); - await _unitOfWork.SaveChangesAsync(TestContext.Current.CancellationToken); + var user = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork); + await TestDataBuilder.SeedClientAsync(_clientRepository, _unitOfWork, user.Id, + email: "ocupado@example.com"); var existingEmail = Email.Create("ocupado@example.com").Value; @@ -171,7 +129,7 @@ public async Task ExistsWithEmailForUserAsync_ShouldReturnTrue_WhenEmailExistsFo [Fact] public async Task ExistsWithEmailForUserAsync_ShouldReturnFalse_WhenEmailDoesNotExistForUser() { - var user = await CreateAndSaveUserAsync(); + var user = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork); var email = Email.Create("inexistente@example.co").Value; var exists = await _clientRepository.ExistsWithEmailForUserAsync( @@ -184,10 +142,9 @@ public async Task ExistsWithEmailForUserAsync_ShouldReturnFalse_WhenEmailDoesNot public async Task ExistsWithEmailForUserAsync_ShouldReturnFalse_WhenExcludeIdMatchesExistingClient() { - var user = await CreateAndSaveUserAsync(); - var client = MakeClient(user.Id, email: "meu@example.com"); - await _clientRepository.AddAsync(client, TestContext.Current.CancellationToken); - await _unitOfWork.SaveChangesAsync(TestContext.Current.CancellationToken); + var user = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork); + var client = await TestDataBuilder.SeedClientAsync(_clientRepository, _unitOfWork, user.Id, + email: "meu@example.com"); var email = Email.Create("meu@example.com").Value; @@ -200,17 +157,12 @@ public async Task [Fact] public async Task ExistsWithEmailForUserAsync_ShouldReturnFalse_WhenEmailBelongsToAnotherUser() { - var user1 = await CreateAndSaveUserAsync(); - - var email2 = Email.Create("outro@example.com").Value; - var doc2 = Document.Create("11222333000181").Value; - var user2 = User.Register("Outro User", email2, doc2, "$argon2id$hash2"); - await _userRepository.AddAsync(user2, TestContext.Current.CancellationToken); - await _unitOfWork.SaveChangesAsync(TestContext.Current.CancellationToken); + var user1 = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork); + var user2 = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork, + name: "Outro User", email: "outro@example.com", document: "11222333000181"); - var client = MakeClient(user1.Id, email: "compartilhado@example.com"); - await _clientRepository.AddAsync(client, TestContext.Current.CancellationToken); - await _unitOfWork.SaveChangesAsync(TestContext.Current.CancellationToken); + await TestDataBuilder.SeedClientAsync(_clientRepository, _unitOfWork, user1.Id, + email: "compartilhado@example.com"); var clientEmail = Email.Create("compartilhado@example.com").Value; diff --git a/tests/Voltiq.Infrastructure.Tests/Persistence/MaterialRepositoryTests.cs b/tests/Voltiq.Infrastructure.Tests/Persistence/MaterialRepositoryTests.cs index 00f131f..f28b155 100644 --- a/tests/Voltiq.Infrastructure.Tests/Persistence/MaterialRepositoryTests.cs +++ b/tests/Voltiq.Infrastructure.Tests/Persistence/MaterialRepositoryTests.cs @@ -1,10 +1,9 @@ using Microsoft.EntityFrameworkCore; using Shouldly; +using Voltiq.CommonTestUtilities.Builders; using Voltiq.CommonTestUtilities.Database; using Voltiq.CommonTestUtilities.Fixtures; -using Voltiq.Domain.Entities; using Voltiq.Domain.Enums; -using Voltiq.Domain.ValueObjects; using Voltiq.Infrastructure.Persistence; using Voltiq.Infrastructure.Persistence.Repositories; using Voltiq.Domain.Interfaces.Repositories.Material; @@ -41,32 +40,11 @@ public async ValueTask DisposeAsync() await _dbContext.DisposeAsync(); } - private static User MakeUser(string email = "joao@example.com", string doc = "529.982.247-25") - { - var e = Email.Create(email).Value; - var d = Document.Create(doc).Value; - return User.Register("João Silva", e, d, "$argon2id$hash"); - } - - private static Material MakeMaterial(Guid userId, string name = "Cabo 10mm") - => Material.Register(userId, name, 15.50m, MaterialUnit.Metro); - - private async Task CreateAndSaveUserAsync(string email = "joao@example.com", string doc = "529.982.247-25") - { - var user = MakeUser(email, doc); - await _userRepository.AddAsync(user); - await _unitOfWork.SaveChangesAsync(); - return user; - } - [Fact] public async Task AddAndGetById_ShouldPersistMaterial() { - var user = await CreateAndSaveUserAsync(); - var material = MakeMaterial(user.Id); - - await _materialRepository.AddAsync(material, TestContext.Current.CancellationToken); - await _unitOfWork.SaveChangesAsync(TestContext.Current.CancellationToken); + var user = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork); + var material = await TestDataBuilder.SeedMaterialAsync(_materialRepository, _unitOfWork, user.Id); var found = await _materialRepository.GetByIdAsync(material.Id, TestContext.Current.CancellationToken); @@ -82,17 +60,13 @@ public async Task AddAndGetById_ShouldPersistMaterial() [Fact] public async Task GetByUserIdAsync_ShouldReturnOnlyMaterialsOfUser() { - var user1 = await CreateAndSaveUserAsync(); - var user2 = await CreateAndSaveUserAsync("maria@example.com", "11222333000181"); + var user1 = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork); + var user2 = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork, + email: "maria@example.com", document: "11222333000181"); - var m1 = MakeMaterial(user1.Id, "Cabo A"); - var m2 = MakeMaterial(user1.Id, "Cabo B"); - var m3 = MakeMaterial(user2.Id, "Disjuntor"); - - await _materialRepository.AddAsync(m1, TestContext.Current.CancellationToken); - await _materialRepository.AddAsync(m2, TestContext.Current.CancellationToken); - await _materialRepository.AddAsync(m3, TestContext.Current.CancellationToken); - await _unitOfWork.SaveChangesAsync(TestContext.Current.CancellationToken); + await TestDataBuilder.SeedMaterialAsync(_materialRepository, _unitOfWork, user1.Id, name: "Cabo A"); + await TestDataBuilder.SeedMaterialAsync(_materialRepository, _unitOfWork, user1.Id, name: "Cabo B"); + await TestDataBuilder.SeedMaterialAsync(_materialRepository, _unitOfWork, user2.Id, name: "Disjuntor"); var user1Materials = await _materialRepository.GetByUserIdAsync(user1.Id, TestContext.Current.CancellationToken); @@ -103,11 +77,8 @@ public async Task GetByUserIdAsync_ShouldReturnOnlyMaterialsOfUser() [Fact] public async Task GetByIdAndUserIdAsync_ShouldReturnMaterial_WhenBelongsToUser() { - var user = await CreateAndSaveUserAsync(); - var material = MakeMaterial(user.Id); - - await _materialRepository.AddAsync(material, TestContext.Current.CancellationToken); - await _unitOfWork.SaveChangesAsync(TestContext.Current.CancellationToken); + var user = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork); + var material = await TestDataBuilder.SeedMaterialAsync(_materialRepository, _unitOfWork, user.Id); var found = await _materialReadOnly.GetByIdAndUserIdAsync(material.Id, user.Id, TestContext.Current.CancellationToken); @@ -118,12 +89,11 @@ public async Task GetByIdAndUserIdAsync_ShouldReturnMaterial_WhenBelongsToUser() [Fact] public async Task GetByIdAndUserIdAsync_ShouldReturnNull_WhenMaterialBelongsToAnotherUser() { - var user1 = await CreateAndSaveUserAsync(); - var user2 = await CreateAndSaveUserAsync("outro@example.com", "11222333000181"); + var user1 = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork); + var user2 = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork, + email: "outro@example.com", document: "11222333000181"); - var material = MakeMaterial(user1.Id); - await _materialRepository.AddAsync(material, TestContext.Current.CancellationToken); - await _unitOfWork.SaveChangesAsync(TestContext.Current.CancellationToken); + var material = await TestDataBuilder.SeedMaterialAsync(_materialRepository, _unitOfWork, user1.Id); var found = await _materialReadOnly.GetByIdAndUserIdAsync(material.Id, user2.Id, TestContext.Current.CancellationToken); @@ -133,13 +103,12 @@ public async Task GetByIdAndUserIdAsync_ShouldReturnNull_WhenMaterialBelongsToAn [Fact] public async Task GetActiveByUserIdAsync_ShouldReturnOnlyActiveMaterials() { - var user = await CreateAndSaveUserAsync(); + var user = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork); - var active = MakeMaterial(user.Id, "Ativo"); - var inactive = MakeMaterial(user.Id, "Inativo"); - inactive.Deactivate(); + await TestDataBuilder.SeedMaterialAsync(_materialRepository, _unitOfWork, user.Id, name: "Ativo"); - await _materialRepository.AddAsync(active, TestContext.Current.CancellationToken); + var inactive = TestDataBuilder.MakeMaterial(user.Id, name: "Inativo"); + inactive.Deactivate(); await _materialRepository.AddAsync(inactive, TestContext.Current.CancellationToken); await _unitOfWork.SaveChangesAsync(TestContext.Current.CancellationToken); @@ -152,12 +121,12 @@ public async Task GetActiveByUserIdAsync_ShouldReturnOnlyActiveMaterials() [Fact] public async Task GetActiveByUserIdAsync_ShouldNotReturnMaterialsOfOtherUser() { - var user1 = await CreateAndSaveUserAsync(); - var user2 = await CreateAndSaveUserAsync("outro@example.com", "11222333000181"); + var user1 = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork); + var user2 = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork, + email: "outro@example.com", document: "11222333000181"); - await _materialRepository.AddAsync(MakeMaterial(user1.Id, "User1 Material"), TestContext.Current.CancellationToken); - await _materialRepository.AddAsync(MakeMaterial(user2.Id, "User2 Material"), TestContext.Current.CancellationToken); - await _unitOfWork.SaveChangesAsync(TestContext.Current.CancellationToken); + await TestDataBuilder.SeedMaterialAsync(_materialRepository, _unitOfWork, user1.Id, name: "User1 Material"); + await TestDataBuilder.SeedMaterialAsync(_materialRepository, _unitOfWork, user2.Id, name: "User2 Material"); var result = await _materialRepository.GetActiveByUserIdAsync(user1.Id, TestContext.Current.CancellationToken); diff --git a/tests/Voltiq.Infrastructure.Tests/Persistence/RefreshTokenRepositoryTests.cs b/tests/Voltiq.Infrastructure.Tests/Persistence/RefreshTokenRepositoryTests.cs index 5d4b16c..e502af2 100644 --- a/tests/Voltiq.Infrastructure.Tests/Persistence/RefreshTokenRepositoryTests.cs +++ b/tests/Voltiq.Infrastructure.Tests/Persistence/RefreshTokenRepositoryTests.cs @@ -1,12 +1,12 @@ using Microsoft.EntityFrameworkCore; using Shouldly; +using Voltiq.CommonTestUtilities.Builders; using Voltiq.CommonTestUtilities.Database; using Voltiq.CommonTestUtilities.Fixtures; -using Voltiq.Domain.Entities; -using Voltiq.Domain.ValueObjects; using Voltiq.Infrastructure.Persistence; using Voltiq.Infrastructure.Persistence.Repositories; using Voltiq.Infrastructure.Persistence.Repositories.TokenRepository; +using Voltiq.Infrastructure.Persistence.Repositories.User; namespace Voltiq.Infrastructure.Tests.Persistence; @@ -15,6 +15,7 @@ public class RefreshTokenRepositoryTests(PostgreSqlContainerFixture fixture) { private ApplicationDbContext _dbContext = null!; private RefreshTokenRepository _repository = null!; + private UserRepository _userRepository = null!; private UnitOfWork _unitOfWork = null!; public async ValueTask InitializeAsync() @@ -23,6 +24,7 @@ public async ValueTask InitializeAsync() await _dbContext.Database.MigrateAsync(); await DatabaseHelper.CleanAsync(_dbContext); + _userRepository = new UserRepository(_dbContext); _repository = new RefreshTokenRepository(_dbContext); _unitOfWork = new UnitOfWork(_dbContext); } @@ -32,25 +34,13 @@ public async ValueTask DisposeAsync() await _dbContext.DisposeAsync(); } - private async Task<(User user, RefreshToken token)> SeedUserAndTokenAsync(string rawToken) - { - var email = Email.Create($"{Guid.NewGuid()}@example.com").Value; - var document = Document.Create("529.982.247-25").Value; - var user = User.Register("Test User", email, document, "$argon2id$hash"); - - await _dbContext.Users.AddAsync(user); - - var token = RefreshToken.Create(rawToken, user.Id, 7); - await _repository.AddAsync(token); - await _unitOfWork.SaveChangesAsync(); - - return (user, token); - } - [Fact] public async Task GetByTokenAsync_WhenTokenExists_ReturnsToken() { - var (_, expected) = await SeedUserAndTokenAsync("my-raw-token-abc"); + var user = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork, + email: $"{Guid.NewGuid()}@example.com"); + var expected = await TestDataBuilder.SeedRefreshTokenAsync(_repository, _unitOfWork, + user.Id, token: "my-raw-token-abc"); var found = await _repository.GetByTokenAsync("my-raw-token-abc", TestContext.Current.CancellationToken); diff --git a/tests/Voltiq.Infrastructure.Tests/Persistence/SoftDeleteTests.cs b/tests/Voltiq.Infrastructure.Tests/Persistence/SoftDeleteTests.cs index a3d7528..3ce8cdd 100644 --- a/tests/Voltiq.Infrastructure.Tests/Persistence/SoftDeleteTests.cs +++ b/tests/Voltiq.Infrastructure.Tests/Persistence/SoftDeleteTests.cs @@ -1,9 +1,8 @@ using Microsoft.EntityFrameworkCore; using Shouldly; +using Voltiq.CommonTestUtilities.Builders; using Voltiq.CommonTestUtilities.Database; using Voltiq.CommonTestUtilities.Fixtures; -using Voltiq.Domain.Entities; -using Voltiq.Domain.ValueObjects; using Voltiq.Infrastructure.Persistence; using Voltiq.Infrastructure.Persistence.Repositories; using Voltiq.Domain.Interfaces.Repositories.Client; @@ -41,30 +40,10 @@ public async ValueTask DisposeAsync() await _dbContext.DisposeAsync(); } - private static User MakeUser() + private async Task<(Voltiq.Domain.Entities.User user, Voltiq.Domain.Entities.Client client)> CreateUserAndClientAsync() { - var email = Email.Create("joao@example.com").Value; - var doc = Document.Create("529.982.247-25").Value; - return User.Register("João Silva", email, doc, "$argon2id$hash"); - } - - private static Client MakeClient(Guid userId) - { - var email = Email.Create("cliente@example.com").Value; - return Client.Register(userId, "Cliente Teste", "(11) 99999-9999", email, - Address.Create("Rua das Flores", "123", "São Paulo", "SP", "01310-100")); - } - - private async Task<(User user, Client client)> CreateUserAndClientAsync() - { - var user = MakeUser(); - await _userRepository.AddAsync(user); - await _unitOfWork.SaveChangesAsync(); - - var client = MakeClient(user.Id); - await _clientRepository.AddAsync(client); - await _unitOfWork.SaveChangesAsync(); - + var user = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork); + var client = await TestDataBuilder.SeedClientAsync(_clientRepository, _unitOfWork, user.Id); return (user, client); } diff --git a/tests/Voltiq.Infrastructure.Tests/Persistence/UserRepositoryTests.cs b/tests/Voltiq.Infrastructure.Tests/Persistence/UserRepositoryTests.cs index fe78946..87ea4fc 100644 --- a/tests/Voltiq.Infrastructure.Tests/Persistence/UserRepositoryTests.cs +++ b/tests/Voltiq.Infrastructure.Tests/Persistence/UserRepositoryTests.cs @@ -1,8 +1,8 @@ using Microsoft.EntityFrameworkCore; using Shouldly; +using Voltiq.CommonTestUtilities.Builders; using Voltiq.CommonTestUtilities.Database; using Voltiq.CommonTestUtilities.Fixtures; -using Voltiq.Domain.Entities; using Voltiq.Domain.ValueObjects; using Voltiq.Infrastructure.Persistence; using Voltiq.Infrastructure.Persistence.Repositories; @@ -36,12 +36,7 @@ public async ValueTask DisposeAsync() [Fact] public async Task AddAndGetById_ShouldPersistUser() { - var email = Email.Create("joao@example.com").Value; - var document = Document.Create("529.982.247-25").Value; - var user = User.Register("João Silva", email, document, "$argon2id$hash"); - - await _userRepository.AddAsync(user, TestContext.Current.CancellationToken); - await _unitOfWork.SaveChangesAsync(TestContext.Current.CancellationToken); + var user = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork); var found = await _userRepository.GetByIdAsync(user.Id, TestContext.Current.CancellationToken); @@ -54,16 +49,11 @@ public async Task AddAndGetById_ShouldPersistUser() [Fact] public async Task ExistsUserAsync_ShouldReturnTrue_WhenEmailOrDocumentExists() { - var email = Email.Create("maria@example.com").Value; - var document = Document.Create("11222333000181").Value; - var user = User.Register("Maria Santos", email, document, "$argon2id$hash"); - - await _userRepository.AddAsync(user, TestContext.Current.CancellationToken); - await _unitOfWork.SaveChangesAsync(TestContext.Current.CancellationToken); + var user = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork, + name: "Maria Santos", email: "maria@example.com", document: "11222333000181"); - var exists = - await _userRepository.ExistsUserAsync(document, email, - TestContext.Current.CancellationToken); + var exists = await _userRepository.ExistsUserAsync( + user.Document, user.Email, TestContext.Current.CancellationToken); exists.ShouldBeTrue(); } @@ -71,15 +61,10 @@ await _userRepository.ExistsUserAsync(document, email, [Fact] public async Task GetByEmailAsync_ShouldReturnUser_WhenEmailExists() { - var email = Email.Create("carlos@example.com").Value; - var document = Document.Create("153.509.460-56").Value; - var user = User.Register("Carlos Souza", email, document, "$argon2id$hash"); - - await _userRepository.AddAsync(user, TestContext.Current.CancellationToken); - await _unitOfWork.SaveChangesAsync(TestContext.Current.CancellationToken); + var user = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork, + name: "Carlos Souza", email: "carlos@example.com", document: "153.509.460-56"); - var found = - await _userRepository.GetByEmailAsync(email, TestContext.Current.CancellationToken); + var found = await _userRepository.GetByEmailAsync(user.Email, TestContext.Current.CancellationToken); found.ShouldNotBeNull(); found.Id.ShouldBe(user.Id);