Files
SIG-CM2.0/tests/SIGCM2.Api.Tests/Usuarios/ListUsuariosEndpointTests.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

152 lines
6.0 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 GET /api/v1/users (UDT-008 B3).
/// </summary>
[Collection("ApiIntegration")]
public sealed class ListUsuariosEndpointTests : IAsyncLifetime
{
private const string TestConnectionString = TestConnectionStrings.ApiTestDb;
private readonly HttpClient _client;
private readonly SqlTestFixture _db;
public ListUsuariosEndpointTests(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<string> GetCajeroTokenAsync()
{
// Seed a cajero user
await using var conn = new SqlConnection(TestConnectionString);
await conn.OpenAsync();
await conn.ExecuteAsync("""
IF NOT EXISTS (SELECT 1 FROM dbo.Usuario WHERE Username = 'cajero_test')
INSERT INTO dbo.Usuario (Username, PasswordHash, Nombre, Apellido, Rol, PermisosJson, Activo, MustChangePassword)
VALUES ('cajero_test', '$2a$12$rmq6tlSAQ8WXhR2CwLCSeuwCJKz/.8Eab95UQCUNfwe4dokeOqMcW', 'Cajero', 'Test', 'cajero', '[]', 1, 0)
""");
var response = await _client.PostAsJsonAsync("/api/v1/auth/login",
new { username = "cajero_test", password = "@Diego550@" });
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadFromJsonAsync<JsonElement>();
return json.GetProperty("accessToken").GetString()!;
}
// ── happy path ────────────────────────────────────────────────────────────
[Fact]
public async Task GET_Users_200_Returns_Paged_Shape()
{
var token = await GetAdminTokenAsync();
var request = new HttpRequestMessage(HttpMethod.Get, "/api/v1/users");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
var response = await _client.SendAsync(request);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var json = await response.Content.ReadFromJsonAsync<JsonElement>();
Assert.True(json.TryGetProperty("items", out _));
Assert.True(json.TryGetProperty("page", out _));
Assert.True(json.TryGetProperty("pageSize", out _));
Assert.True(json.TryGetProperty("total", out _));
}
[Fact]
public async Task GET_Users_Default_PageSize_Is_20()
{
var token = await GetAdminTokenAsync();
var request = new HttpRequestMessage(HttpMethod.Get, "/api/v1/users");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
var response = await _client.SendAsync(request);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var json = await response.Content.ReadFromJsonAsync<JsonElement>();
Assert.Equal(20, json.GetProperty("pageSize").GetInt32());
Assert.Equal(1, json.GetProperty("page").GetInt32());
}
[Fact]
public async Task GET_Users_Filter_Rol_Admin_Returns_Only_Admins()
{
var token = await GetAdminTokenAsync();
var request = new HttpRequestMessage(HttpMethod.Get, "/api/v1/users?rol=admin");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
var response = await _client.SendAsync(request);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var json = await response.Content.ReadFromJsonAsync<JsonElement>();
var items = json.GetProperty("items").EnumerateArray().ToList();
Assert.All(items, item => Assert.Equal("admin", item.GetProperty("rol").GetString()));
}
[Fact]
public async Task GET_Users_PageSize_0_Returns_400()
{
var token = await GetAdminTokenAsync();
var request = new HttpRequestMessage(HttpMethod.Get, "/api/v1/users?pageSize=0");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
var response = await _client.SendAsync(request);
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
}
[Fact]
public async Task GET_Users_Page_0_Returns_400()
{
var token = await GetAdminTokenAsync();
var request = new HttpRequestMessage(HttpMethod.Get, "/api/v1/users?page=0");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
var response = await _client.SendAsync(request);
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
}
// ── auth ──────────────────────────────────────────────────────────────────
[Fact]
public async Task GET_Users_No_Auth_Returns_401()
{
var response = await _client.GetAsync("/api/v1/users");
Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
}
[Fact]
public async Task GET_Users_No_Permission_Returns_403()
{
var token = await GetCajeroTokenAsync();
var request = new HttpRequestMessage(HttpMethod.Get, "/api/v1/users");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
var response = await _client.SendAsync(request);
Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode);
}
}