Files
SIG-CM2.0/tests/SIGCM2.Api.Tests/Usuarios/UpdateUsuarioEndpointTests.cs
dmolinari e5b6c06f64 refactor(tests): Api.Tests apunta a SIGCM2_Test_Api via TestConnectionStrings
Todos los archivos de Api.Tests reemplazan la connection string hardcodeada
por TestConnectionStrings.ApiTestDb. Cada proyecto de tests ahora tiene su
propia base de datos aislada, eliminando la contención entre Application.Tests
y Api.Tests que causaba flakiness.
2026-04-18 21:44:40 -03:00

155 lines
6.3 KiB
C#

using System.Net;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json;
using Dapper;
using Microsoft.Data.SqlClient;
using SIGCM2.TestSupport;
namespace SIGCM2.Api.Tests.Usuarios;
/// <summary>
/// Integration tests for PUT /api/v1/users/{id} (UDT-008 B4).
/// </summary>
[Collection("ApiIntegration")]
public sealed class UpdateUsuarioEndpointTests : IAsyncLifetime
{
private const string TestConnectionString = TestConnectionStrings.ApiTestDb;
private readonly HttpClient _client;
private readonly SqlTestFixture _db;
public UpdateUsuarioEndpointTests(TestWebAppFactory factory)
{
_client = factory.CreateClient();
_db = new SqlTestFixture(TestConnectionString);
}
public async Task InitializeAsync() => await _db.InitializeAsync();
public async Task DisposeAsync() => await _db.DisposeAsync();
private async Task<string> GetAdminTokenAsync()
{
var response = await _client.PostAsJsonAsync("/api/v1/auth/login",
new { username = "admin", password = "@Diego550@" });
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadFromJsonAsync<JsonElement>();
return json.GetProperty("accessToken").GetString()!;
}
private async Task<int> GetAdminIdAsync()
{
await using var conn = new SqlConnection(TestConnectionString);
await conn.OpenAsync();
return await conn.ExecuteScalarAsync<int>("SELECT Id FROM dbo.Usuario WHERE Username = 'admin'");
}
private async Task<int> SeedCajeroAsync(string username = "cajero_update")
{
await using var conn = new SqlConnection(TestConnectionString);
await conn.OpenAsync();
return await conn.ExecuteScalarAsync<int>($"""
IF NOT EXISTS (SELECT 1 FROM dbo.Usuario WHERE Username = '{username}')
INSERT INTO dbo.Usuario (Username, PasswordHash, Nombre, Apellido, Rol, PermisosJson, Activo, MustChangePassword)
VALUES ('{username}', '$2a$12$rmq6tlSAQ8WXhR2CwLCSeuwCJKz/.8Eab95UQCUNfwe4dokeOqMcW', 'Test', 'Usuario', 'cajero', '[]', 1, 0);
SELECT Id FROM dbo.Usuario WHERE Username = '{username}'
""");
}
private async Task<string> GetCajeroTokenAsync()
{
var id = await SeedCajeroAsync("cajero_update_auth");
var response = await _client.PostAsJsonAsync("/api/v1/auth/login",
new { username = "cajero_update_auth", password = "@Diego550@" });
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadFromJsonAsync<JsonElement>();
return json.GetProperty("accessToken").GetString()!;
}
[Fact]
public async Task PUT_Users_Id_200_Returns_Updated_Detail()
{
var token = await GetAdminTokenAsync();
var targetId = await SeedCajeroAsync("cajero_upd_happy");
var request = new HttpRequestMessage(HttpMethod.Put, $"/api/v1/users/{targetId}");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
request.Content = JsonContent.Create(new { nombre = "Editado", apellido = "Test", email = (string?)null, rol = "cajero", activo = true });
var response = await _client.SendAsync(request);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var json = await response.Content.ReadFromJsonAsync<JsonElement>();
Assert.Equal("Editado", json.GetProperty("nombre").GetString());
}
[Fact]
public async Task PUT_Users_Id_400_Invalid_Email()
{
var token = await GetAdminTokenAsync();
var targetId = await SeedCajeroAsync("cajero_upd_email");
var request = new HttpRequestMessage(HttpMethod.Put, $"/api/v1/users/{targetId}");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
request.Content = JsonContent.Create(new { nombre = "A", apellido = "B", email = "not-an-email", rol = "cajero", activo = true });
var response = await _client.SendAsync(request);
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
}
[Fact]
public async Task PUT_Users_Id_400_Last_Admin_Lockout_With_Error_Key()
{
var token = await GetAdminTokenAsync();
var adminId = await GetAdminIdAsync();
var request = new HttpRequestMessage(HttpMethod.Put, $"/api/v1/users/{adminId}");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
request.Content = JsonContent.Create(new { nombre = "Admin", apellido = "Sys", email = (string?)null, rol = "cajero", activo = true });
var response = await _client.SendAsync(request);
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
var body = await response.Content.ReadAsStringAsync();
Assert.Contains("last-admin-lockout", body, StringComparison.OrdinalIgnoreCase);
}
[Fact]
public async Task PUT_Users_Id_404_Not_Found()
{
var token = await GetAdminTokenAsync();
var request = new HttpRequestMessage(HttpMethod.Put, "/api/v1/users/9999");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
request.Content = JsonContent.Create(new { nombre = "A", apellido = "B", email = (string?)null, rol = "cajero", activo = true });
var response = await _client.SendAsync(request);
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}
[Fact]
public async Task PUT_Users_Id_403_No_Permission()
{
var token = await GetCajeroTokenAsync();
var request = new HttpRequestMessage(HttpMethod.Put, "/api/v1/users/1");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
request.Content = JsonContent.Create(new { nombre = "A", apellido = "B", email = (string?)null, rol = "cajero", activo = true });
var response = await _client.SendAsync(request);
Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode);
}
[Fact]
public async Task PUT_Users_Id_401_No_Auth()
{
var request = new HttpRequestMessage(HttpMethod.Put, "/api/v1/users/1");
request.Content = JsonContent.Create(new { nombre = "A", apellido = "B", email = (string?)null, rol = "cajero", activo = true });
var response = await _client.SendAsync(request);
Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
}
}