Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/workflow-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ jobs:
with:
dotnet-version: 10.0.x

- name: Set UTF-8 locale
run: |
sudo apt-get update
sudo apt-get install -y locales
sudo locale-gen en_US.UTF-8
echo "LANG=en_US.UTF-8" >> $GITHUB_ENV
echo "LC_ALL=en_US.UTF-8" >> $GITHUB_ENV

Comment thread
jldsilva marked this conversation as resolved.
- name: Restore dependencies
run: dotnet restore

Expand Down
3 changes: 0 additions & 3 deletions CodeCoverage.runsettings
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<RunConfiguration>
<MaxCpuCount>1</MaxCpuCount>
</RunConfiguration>
<DataCollectionRunSettings>
<DataCollectors>
<DataCollector friendlyName="Code Coverage" uri="datacollector://Microsoft/CodeCoverage/2.0">
Expand Down
59 changes: 32 additions & 27 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,56 +3,61 @@
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
</PropertyGroup>

<ItemGroup Label=".Net Packages: Essentials">
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.1" />
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="10.0.1" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="10.0.1" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.1" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="10.0.1" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.1" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.1" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.1" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="10.0.1" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.1" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="10.0.1" />
<PackageVersion Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="10.0.1" />
<PackageVersion Include="Microsoft.Extensions.Configuration.FileExtensions" Version="10.0.1" />
<PackageVersion Include="Microsoft.Extensions.Configuration.UserSecrets" Version="10.0.1" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.1" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="10.0.1" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="10.0.1" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.1" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.1" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.1" />
</ItemGroup>

<ItemGroup Label="System Packages">
<PackageVersion Include="AspNetCore.HealthChecks.NpgSql" Version="9.0.0" />
<PackageVersion Include="Dapper" Version="2.1.66" />
<PackageVersion Include="Google.Apis.Gmail.v1" Version="1.72.0.3966" />
<PackageVersion Include="EFCore.BulkExtensions.Dotnet10" Version="10.0.0" />
<PackageVersion Include="EFCore.BulkExtensions.Dotnet10.PostgreSql" Version="10.0.0" />
<PackageVersion Include="Google.Apis.Gmail.v1" Version="1.73.0.3987" />
<PackageVersion Include="itext" Version="9.4.0" />
<PackageVersion Include="itext.bouncy-castle-adapter" Version="9.4.0" />
<PackageVersion Include="itext.bouncy-castle-fips-adapter" Version="9.4.0" />
<PackageVersion Include="Mapster" Version="7.4.0" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.Abstractions" Version="2.3.0" />
<PackageVersion Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.3.0" />
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="10.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="10.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="10.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="10.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="10.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="10.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.FileExtensions" Version="10.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.UserSecrets" Version="10.0.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.0" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="10.0.0" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="10.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.0" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.0" />
<PackageVersion Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.22.1" />
<PackageVersion Include="Npgsql" Version="10.0.0" />
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.0" />
<PackageVersion Include="Quartz" Version="3.15.1" />
<PackageVersion Include="Scalar.AspNetCore" Version="2.11.0" />
<PackageVersion Include="Scalar.AspNetCore" Version="2.11.8" />
<PackageVersion Include="Scrutor" Version="7.0.0" />
<PackageVersion Include="SonarAnalyzer.CSharp" Version="10.16.1.129956" />
<PackageVersion Include="SonarAnalyzer.CSharp" Version="10.17.0.131074" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="8.15.0" />
<PackageVersion Include="Telegram.Bot" Version="22.7.5" />
<PackageVersion Include="Z.EntityFramework.Extensions.EFCore" Version="10.105.0" />
<PackageVersion Include="Telegram.Bot" Version="22.7.6" />
</ItemGroup>

<ItemGroup Label="Unit Tests Packages: Support">
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.0" />
<PackageVersion Include="Bogus" Version="35.6.5" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.1" />
<PackageVersion Include="NetArchTest.Rules" Version="1.3.2" />
<PackageVersion Include="NSubstitute" Version="5.3.0" />
<PackageVersion Include="NSubstitute.Analyzers.CSharp" Version="1.0.17" />
<PackageVersion Include="Shouldly" Version="4.3.0" />
<PackageVersion Include="System.CodeDom" Version="10.0.0" />
<PackageVersion Include="System.CodeDom" Version="10.0.1" />
</ItemGroup>

<ItemGroup Label="Unit Tests Packages: Essentials">
Expand Down
145 changes: 42 additions & 103 deletions InvoiceReminder.API.UnitTests/Endpoints/InvoiceEndpointsTests.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Bogus;
using InvoiceReminder.API.UnitTests.Factories;
using InvoiceReminder.Application.Interfaces;
using InvoiceReminder.Application.ViewModels;
Expand All @@ -22,6 +23,8 @@ public sealed class InvoiceEndpointsTests
private readonly HttpClient _client;
private readonly IAuthorizationService _authorizationService;
private readonly IInvoiceAppService _invoiceAppService;
private readonly Faker<InvoiceViewModel> _invoiceViewModelFaker;
private readonly Faker _faker;
private const string basepath = "/api/invoice";

public TestContext TestContext { get; set; }
Expand All @@ -34,6 +37,26 @@ public InvoiceEndpointsTests()
_client = factory.CreateClient();
_authorizationService = serviceProvider.GetRequiredService<IAuthorizationService>();
_invoiceAppService = serviceProvider.GetRequiredService<IInvoiceAppService>();
_faker = new Faker();

_invoiceViewModelFaker = new Faker<InvoiceViewModel>()
.RuleFor(i => i.Id, faker => faker.Random.Guid())
.RuleFor(i => i.UserId, faker => faker.Random.Guid())
.RuleFor(i => i.Bank, faker => faker.PickRandom(
"Banco do Brasil",
"Bradesco",
"Itaú",
"Caixa Econômica Federal",
"Santander",
"Safra",
"Citibank",
"BTG Pactual"))
.RuleFor(i => i.Beneficiary, faker => faker.Person.FullName)
.RuleFor(i => i.Amount, faker => faker.Finance.Amount(10, 10000))
.RuleFor(i => i.Barcode, faker => faker.Random.AlphaNumeric(44))
.RuleFor(i => i.DueDate, faker => faker.Date.Future().ToUniversalTime())
.RuleFor(i => i.CreatedAt, faker => faker.Date.Past().ToUniversalTime())
.RuleFor(i => i.UpdatedAt, faker => faker.Date.Recent().ToUniversalTime());
}

#region MapGet Tests
Expand All @@ -44,29 +67,8 @@ public async Task GetAllInvoices_WhenUserIsAuthenticated_ShouldReturnOk()
var request = new HttpRequestMessage(HttpMethod.Get, basepath);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "test_token");

var expectedResult = Result<IEnumerable<InvoiceViewModel>>.Success(
[
new() {
Id = Guid.NewGuid(),
Bank = "Banco do Brasil",
Beneficiary = "João da Silva",
Amount = 100.00m,
Barcode = "12345678901234567890123456789012345678901234",
DueDate = DateTime.UtcNow.AddDays(30),
CreatedAt = DateTime.UtcNow,
UpdatedAt = DateTime.UtcNow
},
new() {
Id = Guid.NewGuid(),
Bank = "Banco do Brasil",
Beneficiary = "José da Silva",
Amount = 100.00m,
Barcode = "12345678901234567890123456789012345678901234",
DueDate = DateTime.UtcNow.AddDays(30),
CreatedAt = DateTime.UtcNow,
UpdatedAt = DateTime.UtcNow
}
]);
var invoices = _invoiceViewModelFaker.Generate(2);
var expectedResult = Result<IEnumerable<InvoiceViewModel>>.Success(invoices);

_ = _invoiceAppService.GetAll().Returns(expectedResult);

Expand Down Expand Up @@ -140,17 +142,7 @@ public async Task GetInvoiceById_WhenUserIsAuthenticated_ShouldReturnOk()
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "test_token");

var expectedResult = Result<InvoiceViewModel>.Success(
new()
{
Id = id,
Bank = "Banco do Brasil",
Beneficiary = "João da Silva",
Amount = 100.00m,
Barcode = "12345678901234567890123456789012345678901234",
DueDate = DateTime.UtcNow.AddDays(30),
CreatedAt = DateTime.UtcNow,
UpdatedAt = DateTime.UtcNow
});
_invoiceViewModelFaker.Clone().RuleFor(i => i.Id, id).Generate());

_ = _invoiceAppService.GetByIdAsync(Arg.Any<Guid>(), Arg.Any<CancellationToken>()).Returns(expectedResult);

Expand Down Expand Up @@ -274,21 +266,12 @@ public async Task GetInvoiceById_WhenUserIsAuthenticatedButNotExists_ShouldRetur
public async Task GetInvoiceByBarcode_WhenUserIsAuthenticated_ShouldReturnOk()
{
// Arrange
var value = "12345678901234567890123456789012345678901234";
var request = new HttpRequestMessage(HttpMethod.Get, $"{basepath}/getby-barcode/{value}");
var barcode = _faker.Random.AlphaNumeric(44);
var request = new HttpRequestMessage(HttpMethod.Get, $"{basepath}/getby-barcode/{barcode}");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "test_token");

var expectedResult = Result<InvoiceViewModel>.Success(new()
{
Id = Guid.NewGuid(),
Bank = "Banco do Brasil",
Beneficiary = "João da Silva",
Amount = 100.00m,
Barcode = "12345678901234567890123456789012345678901234",
DueDate = DateTime.UtcNow.AddDays(30),
CreatedAt = DateTime.UtcNow,
UpdatedAt = DateTime.UtcNow
});
var expectedResult = Result<InvoiceViewModel>.Success(
_invoiceViewModelFaker.Clone().RuleFor(i => i.Barcode, barcode).Generate());

_ = _invoiceAppService.GetByBarcodeAsync(Arg.Any<string>(), Arg.Any<CancellationToken>())
.Returns(expectedResult);
Expand All @@ -313,8 +296,8 @@ public async Task GetInvoiceByBarcode_WhenUserIsAuthenticated_ShouldReturnOk()
public async Task GetInvoiceByBarcode_WhenUserIsNotAuthenticated_ShouldReturnUnauthorized()
{
// Arrange
var value = "12345678901234567890123456789012345678901234";
var request = new HttpRequestMessage(HttpMethod.Get, $"{basepath}/getby-barcode/{value}");
var barcode = _faker.Random.AlphaNumeric(44);
var request = new HttpRequestMessage(HttpMethod.Get, $"{basepath}/getby-barcode/{barcode}");

_ = _authorizationService.AuthorizeAsync(Arg.Any<ClaimsPrincipal>(), Arg.Any<object>(),
Arg.Any<IEnumerable<IAuthorizationRequirement>>())
Expand All @@ -331,8 +314,8 @@ public async Task GetInvoiceByBarcode_WhenUserIsNotAuthenticated_ShouldReturnUna
public async Task GetInvoiceByBarcode_WhenUserIsAuthenticatedButServiceFails_ShouldReturnBadRequest()
{
// Arrange
var value = "12345678901234567890123456789012345678901234";
var request = new HttpRequestMessage(HttpMethod.Get, $"{basepath}/getby-barcode/{value}");
var barcode = _faker.Random.AlphaNumeric(44);
var request = new HttpRequestMessage(HttpMethod.Get, $"{basepath}/getby-barcode/{barcode}");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "test_token");

_ = _invoiceAppService.GetByBarcodeAsync(Arg.Any<string>(), Arg.Any<CancellationToken>())
Expand All @@ -358,8 +341,8 @@ public async Task GetInvoiceByBarcode_WhenUserIsAuthenticatedButServiceFails_Sho
public async Task GetInvoiceByBarcode_WhenUserIsAuthenticatedButServiceFails_ShouldReturnInternalServerError()
{
// Arrange
var value = "12345678901234567890123456789012345678901234";
var request = new HttpRequestMessage(HttpMethod.Get, $"{basepath}/getby-barcode/{value}");
var barcode = _faker.Random.AlphaNumeric(44);
var request = new HttpRequestMessage(HttpMethod.Get, $"{basepath}/getby-barcode/{barcode}");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "test_token");

_ = _invoiceAppService.GetByBarcodeAsync(Arg.Any<string>(), Arg.Any<CancellationToken>())
Expand All @@ -385,8 +368,8 @@ public async Task GetInvoiceByBarcode_WhenUserIsAuthenticatedButServiceFails_Sho
public async Task GetInvoiceByBarcode_WhenUserIsAuthenticatedButNotExists_ShouldReturnNotFound()
{
// Arrange
var value = "12345678901234567890123456789012345678901234";
var request = new HttpRequestMessage(HttpMethod.Get, $"{basepath}/getby-barcode/{value}");
var barcode = _faker.Random.AlphaNumeric(44);
var request = new HttpRequestMessage(HttpMethod.Get, $"{basepath}/getby-barcode/{barcode}");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "test_token");

var expectedResult = Result<InvoiceViewModel>.Failure($"Invoice not Found.");
Expand Down Expand Up @@ -421,18 +404,7 @@ public async Task CreateInvoice_WhenUserIsAuthenticated_ShouldReturnCreated()
var request = new HttpRequestMessage(HttpMethod.Post, basepath);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "test_token");

var invoiceViewModel = new InvoiceViewModel
{
Id = Guid.NewGuid(),
Bank = "Banco do Brasil",
Beneficiary = "João da Silva",
Amount = 100.00m,
Barcode = "12345678901234567890123456789012345678901234",
DueDate = DateTime.UtcNow.AddDays(30),
CreatedAt = DateTime.UtcNow,
UpdatedAt = DateTime.UtcNow
};

var invoiceViewModel = _invoiceViewModelFaker.Generate();
var expectedResult = Result<InvoiceViewModel>.Success(invoiceViewModel);

_ = _invoiceAppService.AddAsync(Arg.Any<InvoiceViewModel>(), Arg.Any<CancellationToken>())
Expand Down Expand Up @@ -479,18 +451,7 @@ public async Task CreateInvoice_WhenUserIsAuthenticatedButServiceFails_ShouldRet
var request = new HttpRequestMessage(HttpMethod.Post, basepath);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "test_token");

var invoiceViewModel = new InvoiceViewModel
{
Id = Guid.NewGuid(),
Bank = "Banco do Brasil",
Beneficiary = "João da Silva",
Amount = 100.00m,
Barcode = "12345678901234567890123456789012345678901234",
DueDate = DateTime.UtcNow.AddDays(30),
CreatedAt = DateTime.UtcNow,
UpdatedAt = DateTime.UtcNow
};

var invoiceViewModel = _invoiceViewModelFaker.Generate();
var expectedResult = Result<InvoiceViewModel>.Failure("Service error");

_ = _invoiceAppService.AddAsync(Arg.Any<InvoiceViewModel>(), Arg.Any<CancellationToken>())
Expand Down Expand Up @@ -524,18 +485,7 @@ public async Task UpdateInvoice_WhenUserIsAuthenticated_ShouldReturnOk()
var request = new HttpRequestMessage(HttpMethod.Put, basepath);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "test_token");

var invoiceViewModel = new InvoiceViewModel
{
Id = Guid.NewGuid(),
Bank = "Banco do Brasil",
Beneficiary = "João da Silva",
Amount = 100.00m,
Barcode = "12345678901234567890123456789012345678901234",
DueDate = DateTime.UtcNow.AddDays(30),
CreatedAt = DateTime.UtcNow,
UpdatedAt = DateTime.UtcNow
};

var invoiceViewModel = _invoiceViewModelFaker.Generate();
var expectedResult = Result<InvoiceViewModel>.Success(invoiceViewModel);

_ = _invoiceAppService.UpdateAsync(Arg.Any<InvoiceViewModel>(), Arg.Any<CancellationToken>())
Expand Down Expand Up @@ -582,18 +532,7 @@ public async Task UpdateInvoice_WhenUserIsAuthenticatedButServiceFails_ShouldRet
var request = new HttpRequestMessage(HttpMethod.Put, basepath);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "test_token");

var invoiceViewModel = new InvoiceViewModel
{
Id = Guid.NewGuid(),
Bank = "Banco do Brasil",
Beneficiary = "João da Silva",
Amount = 100.00m,
Barcode = "12345678901234567890123456789012345678901234",
DueDate = DateTime.UtcNow.AddDays(30),
CreatedAt = DateTime.UtcNow,
UpdatedAt = DateTime.UtcNow
};

var invoiceViewModel = _invoiceViewModelFaker.Generate();
var expectedResult = Result<InvoiceViewModel>.Failure("Service error");

_ = _invoiceAppService.UpdateAsync(Arg.Any<InvoiceViewModel>(), Arg.Any<CancellationToken>())
Expand Down
Loading