using Dapper; using SIGCM2.Infrastructure.Persistence; using SIGCM2.TestSupport; namespace SIGCM2.Application.Tests.Integration; /// /// Integration tests for IUsuarioRepository.UpdatePermisosJsonAsync (UDT-009). /// Uses SIGCM2_Test_App database via shared SqlTestFixture. /// [Collection("Database")] public sealed class UsuarioRepository_PermisosTests : IAsyncLifetime { private readonly SqlTestFixture _db; private UsuarioRepository _repository = null!; public UsuarioRepository_PermisosTests(SqlTestFixture db) { _db = db; } public async Task InitializeAsync() { await _db.ResetAndSeedAsync(); var factory = new SqlConnectionFactory(TestConnectionStrings.AppTestDb); _repository = new UsuarioRepository(factory); // Seed a test user await _db.Connection.ExecuteAsync(""" INSERT INTO dbo.Usuario (Username, PasswordHash, Nombre, Apellido, Rol, PermisosJson, Activo, MustChangePassword) VALUES ('testuser', '$2a$12$hash', 'Test', 'User', 'cajero', '{"grant":[],"deny":[]}', 1, 0) """); } public Task DisposeAsync() => Task.CompletedTask; // UPJ-01: UpdatePermisosJsonAsync persists PermisosJson and FechaModificacion [Fact] public async Task UpdatePermisosJsonAsync_PersistsJsonAndFechaModificacion() { // Arrange var userId = await _db.Connection.QuerySingleAsync( "SELECT Id FROM dbo.Usuario WHERE Username = 'testuser'"); var newJson = """{"grant":["textos:editar"],"deny":[]}"""; var fechaMod = DateTime.UtcNow; // Act await _repository.UpdatePermisosJsonAsync(userId, newJson, fechaMod); // Assert var row = await _db.Connection.QuerySingleAsync<(string PermisosJson, DateTime? FechaModificacion)>( "SELECT PermisosJson, FechaModificacion FROM dbo.Usuario WHERE Id = @Id", new { Id = userId }); Assert.Equal(newJson, row.PermisosJson); Assert.NotNull(row.FechaModificacion); // Allow 2-second tolerance for DB round-trip Assert.True( Math.Abs((row.FechaModificacion!.Value - fechaMod).TotalSeconds) < 2, $"FechaModificacion {row.FechaModificacion} is too far from {fechaMod}"); } // UPJ-02: UpdatePermisosJsonAsync with non-existent id → no throw (UPDATE affects 0 rows) [Fact] public async Task UpdatePermisosJsonAsync_NonExistentId_NoThrow() { // Should not throw — UPDATE with 0 rows affected is a no-op await _repository.UpdatePermisosJsonAsync(99999, """{"grant":[],"deny":[]}""", DateTime.UtcNow); } // UPJ-03: GetByIdAsync after update reflects new PermisosJson [Fact] public async Task UpdatePermisosJsonAsync_GetByIdReflectsChange() { // Arrange var userId = await _db.Connection.QuerySingleAsync( "SELECT Id FROM dbo.Usuario WHERE Username = 'testuser'"); var newJson = """{"grant":["pauta:azanu:ver"],"deny":["ventas:contado:cobrar"]}"""; // Act await _repository.UpdatePermisosJsonAsync(userId, newJson, DateTime.UtcNow); // Assert — read back through the repo var usuario = await _repository.GetByIdAsync(userId); Assert.NotNull(usuario); Assert.Equal(newJson, usuario!.PermisosJson); } }