Skip to content
Open
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
3 changes: 3 additions & 0 deletions App-de-Vecinos.sln
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NeighborValidationService",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommonData", "Microservices\CommonData\CommonData.csproj", "{3DE3C7A6-F7B6-49F3-AA8A-3285462BF2B3}"
EndProject

Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AppVecinos.API.Tests", "AppVecinos.API.Tests\AppVecinos.API.Tests.csproj", "{63EFC224-88F5-42EA-8F4E-260836DAF86E}"

EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -61,6 +63,7 @@ Global
{63EFC224-88F5-42EA-8F4E-260836DAF86E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{63EFC224-88F5-42EA-8F4E-260836DAF86E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{63EFC224-88F5-42EA-8F4E-260836DAF86E}.Release|Any CPU.Build.0 = Release|Any CPU

EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
34 changes: 19 additions & 15 deletions AppVecinos.API.Tests/AppVecinos.API.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>


<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />

<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand All @@ -19,14 +21,16 @@
<PackageReference Include="coverlet.collector" Version="6.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Moq" Version="4.20.70" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.11" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="9.0.0" />

</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\AppVecinos.API\AppVecinos.API.csproj" />
</ItemGroup>

</Project>

</ItemGroup>

</Project>

179 changes: 179 additions & 0 deletions AppVecinos.API.Tests/LoginEndpointTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
using System.Net;
using System.Net.Http.Json;
using System.Text;
using AppVecinos.API.Extensions;
using AppVecinos.API.Models;
using AppVecinos.API.Services;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Xunit;

namespace AppVecinos.API.Tests
{
public class LoginEndpointTests
{
[Fact]
public async Task Login_WithValidCredentials_ReturnsToken()
{
// Arrange
var mockNeighborService = new Mock<INeighborService>();
var testNeighbor = new Neighbor
{
Id = 1,
Name = "Test User",
Number = 123,
User = "testuser",
Password = "password",
Level = "Admin",
Status = "Active"
};

mockNeighborService
.Setup(service => service.GetNeighborByCredentialsAsync("testuser", "password"))
.ReturnsAsync(testNeighbor);

// Create a mock configuration with JWT settings
var inMemorySettings = new Dictionary<string, string> {
{"JwtSettings:SecretKey", "TestSecretKeyWithAtLeast32Characters1234567890"},
{"JwtSettings:Issuer", "TestIssuer"},
{"JwtSettings:Audience", "TestAudience"}
};

var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(inMemorySettings)
.Build();

// Create a test server with the application
var webHostBuilder = new WebHostBuilder()
.UseConfiguration(configuration)
.ConfigureServices(services =>
{
services.AddSingleton<IConfiguration>(configuration);
services.AddScoped<INeighborService>(_ => mockNeighborService.Object);
services.AddJwtAuthenticationAndAuthorization(configuration);
services.AddEndpointsApiExplorer();
})
.UseStartup<TestStartup>();

var testServer = new TestServer(webHostBuilder);
var client = testServer.CreateClient();

// Act
var loginRequest = new LoginRequest
{
Username = "testuser",
Password = "password"
};

var response = await client.PostAsJsonAsync("/login", loginRequest);

// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var responseContent = await response.Content.ReadAsStringAsync();
Assert.Contains("token", responseContent);

// Verify service was called with correct parameters
mockNeighborService.Verify(
service => service.GetNeighborByCredentialsAsync("testuser", "password"),
Times.Once);
}

[Fact]
public async Task Login_WithInvalidCredentials_ReturnsUnauthorized()
{
// Arrange
var mockNeighborService = new Mock<INeighborService>();

// Setup to return null for invalid credentials
mockNeighborService
.Setup(service => service.GetNeighborByCredentialsAsync("testuser", "wrongpassword"))
.ReturnsAsync((Neighbor)null);

// Create a mock configuration with JWT settings
var inMemorySettings = new Dictionary<string, string> {
{"JwtSettings:SecretKey", "TestSecretKeyWithAtLeast32Characters1234567890"},
{"JwtSettings:Issuer", "TestIssuer"},
{"JwtSettings:Audience", "TestAudience"}
};

var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(inMemorySettings)
.Build();

// Create a test server with the application
var webHostBuilder = new WebHostBuilder()
.UseConfiguration(configuration)
.ConfigureServices(services =>
{
services.AddSingleton<IConfiguration>(configuration);
services.AddScoped<INeighborService>(_ => mockNeighborService.Object);
services.AddJwtAuthenticationAndAuthorization(configuration);
services.AddEndpointsApiExplorer();
})
.UseStartup<TestStartup>();

var testServer = new TestServer(webHostBuilder);
var client = testServer.CreateClient();

// Act
var loginRequest = new LoginRequest
{
Username = "testuser",
Password = "wrongpassword"
};

var response = await client.PostAsJsonAsync("/login", loginRequest);

// Assert
Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);

// Verify service was called with correct parameters
mockNeighborService.Verify(
service => service.GetNeighborByCredentialsAsync("testuser", "wrongpassword"),
Times.Once);
}
}

// Create a minimal startup class for the test server
public class TestStartup
{
public IConfiguration Configuration { get; }

public TestStartup(IConfiguration configuration)
{
Configuration = configuration;
}

public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
}

public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
// Setup login endpoint for testing
endpoints.MapPost("/login", async (INeighborService service, LoginRequest loginRequest, IConfiguration configuration) =>
{
var result = await service.GetNeighborByCredentialsAsync(loginRequest.Username, loginRequest.Password);
if (result != null)
{
var token = AuthenticationServiceExtensions.GenerateJwtToken(loginRequest.Username, result.Level, configuration);
return Results.Ok(new { Token = token });
}
return Results.Unauthorized();
});
});
}
}
}