2026-04-13 21:36:09 -03:00
|
|
|
using SIGCM2.Domain.Entities;
|
|
|
|
|
|
|
|
|
|
namespace SIGCM2.Application.Tests.Domain;
|
|
|
|
|
|
2026-04-15 17:36:46 -03:00
|
|
|
// ── UDT-008 tests ────────────────────────────────────────────────────────────
|
|
|
|
|
|
2026-04-13 21:36:09 -03:00
|
|
|
public class UsuarioTests
|
|
|
|
|
{
|
|
|
|
|
// Happy path: constructor sets all properties correctly
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Constructor_SetsAllProperties()
|
|
|
|
|
{
|
|
|
|
|
var usuario = new Usuario(
|
|
|
|
|
id: 1,
|
|
|
|
|
username: "admin",
|
|
|
|
|
passwordHash: "$2a$12$hash",
|
|
|
|
|
nombre: "Administrador",
|
|
|
|
|
apellido: "Sistema",
|
|
|
|
|
email: null,
|
|
|
|
|
rol: "admin",
|
|
|
|
|
permisosJson: "[\"*\"]",
|
|
|
|
|
activo: true
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
Assert.Equal(1, usuario.Id);
|
|
|
|
|
Assert.Equal("admin", usuario.Username);
|
|
|
|
|
Assert.Equal("$2a$12$hash", usuario.PasswordHash);
|
|
|
|
|
Assert.Equal("Administrador", usuario.Nombre);
|
|
|
|
|
Assert.Equal("Sistema", usuario.Apellido);
|
|
|
|
|
Assert.Null(usuario.Email);
|
|
|
|
|
Assert.Equal("admin", usuario.Rol);
|
|
|
|
|
Assert.Equal("[\"*\"]", usuario.PermisosJson);
|
|
|
|
|
Assert.True(usuario.Activo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Triangulation: inactive user
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Constructor_WithActivo_False_SetsActivo_False()
|
|
|
|
|
{
|
|
|
|
|
var usuario = new Usuario(
|
|
|
|
|
id: 2,
|
|
|
|
|
username: "vendedor",
|
|
|
|
|
passwordHash: "$2a$12$hash2",
|
|
|
|
|
nombre: "Juan",
|
|
|
|
|
apellido: "Pérez",
|
|
|
|
|
email: "juan@example.com",
|
|
|
|
|
rol: "vendedor",
|
|
|
|
|
permisosJson: "[]",
|
|
|
|
|
activo: false
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
Assert.Equal(2, usuario.Id);
|
|
|
|
|
Assert.Equal("vendedor", usuario.Username);
|
|
|
|
|
Assert.Equal("juan@example.com", usuario.Email);
|
|
|
|
|
Assert.Equal("vendedor", usuario.Rol);
|
|
|
|
|
Assert.Equal("[]", usuario.PermisosJson);
|
|
|
|
|
Assert.False(usuario.Activo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Activo property reflects the actual state
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Activo_IsTrue_WhenConstructedActive()
|
|
|
|
|
{
|
|
|
|
|
var usuario = new Usuario(1, "admin", "$2a$12$hash", "Admin", "Sys", null, "admin", "[\"*\"]", true);
|
|
|
|
|
Assert.True(usuario.Activo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Activo_IsFalse_WhenConstructedInactive()
|
|
|
|
|
{
|
|
|
|
|
var usuario = new Usuario(2, "inactive", "$2a$12$hash", "Old", "User", null, "consulta", "[]", false);
|
|
|
|
|
Assert.False(usuario.Activo);
|
|
|
|
|
}
|
2026-04-15 17:36:46 -03:00
|
|
|
|
|
|
|
|
// ── UDT-008: new properties ───────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void ForCreation_Defaults_MustChangePassword_False()
|
|
|
|
|
{
|
|
|
|
|
var u = Usuario.ForCreation("user", "hash", "A", "B", null, "cajero");
|
|
|
|
|
Assert.False(u.MustChangePassword);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void ForCreation_Defaults_FechaModificacion_Null()
|
|
|
|
|
{
|
|
|
|
|
var u = Usuario.ForCreation("user", "hash", "A", "B", null, "cajero");
|
|
|
|
|
Assert.Null(u.FechaModificacion);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void ForCreation_Defaults_UltimoLogin_Null()
|
|
|
|
|
{
|
|
|
|
|
var u = Usuario.ForCreation("user", "hash", "A", "B", null, "cajero");
|
|
|
|
|
Assert.Null(u.UltimoLogin);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── UDT-008: WithUpdatedProfile ──────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void WithUpdatedProfile_Returns_NewInstance()
|
|
|
|
|
{
|
|
|
|
|
var u = MakeUsuario();
|
2026-04-18 10:12:32 -03:00
|
|
|
var updated = u.WithUpdatedProfile("NuevoNombre", "NuevoApellido", "new@x.com", "cajero", true, DateTime.UtcNow);
|
2026-04-15 17:36:46 -03:00
|
|
|
Assert.NotSame(u, updated);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void WithUpdatedProfile_Sets_Fields_Correctly()
|
|
|
|
|
{
|
|
|
|
|
var u = MakeUsuario();
|
2026-04-18 10:12:32 -03:00
|
|
|
var updated = u.WithUpdatedProfile("Pedro", "Gómez", "p@g.com", "cajero", false, DateTime.UtcNow);
|
2026-04-15 17:36:46 -03:00
|
|
|
Assert.Equal("Pedro", updated.Nombre);
|
|
|
|
|
Assert.Equal("Gómez", updated.Apellido);
|
|
|
|
|
Assert.Equal("p@g.com", updated.Email);
|
|
|
|
|
Assert.Equal("cajero", updated.Rol);
|
|
|
|
|
Assert.False(updated.Activo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void WithUpdatedProfile_Sets_FechaModificacion_To_UtcNow()
|
|
|
|
|
{
|
|
|
|
|
var before = DateTime.UtcNow.AddSeconds(-1);
|
2026-04-18 10:12:32 -03:00
|
|
|
var now = DateTime.UtcNow;
|
2026-04-15 17:36:46 -03:00
|
|
|
var u = MakeUsuario();
|
2026-04-18 10:12:32 -03:00
|
|
|
var updated = u.WithUpdatedProfile("A", "B", null, "admin", true, now);
|
2026-04-15 17:36:46 -03:00
|
|
|
Assert.NotNull(updated.FechaModificacion);
|
|
|
|
|
Assert.True(updated.FechaModificacion >= before);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void WithUpdatedProfile_Preserves_Immutable_Fields()
|
|
|
|
|
{
|
|
|
|
|
var u = MakeUsuario();
|
2026-04-18 10:12:32 -03:00
|
|
|
var updated = u.WithUpdatedProfile("X", "Y", null, "cajero", true, DateTime.UtcNow);
|
2026-04-15 17:36:46 -03:00
|
|
|
Assert.Equal(u.Id, updated.Id);
|
|
|
|
|
Assert.Equal(u.Username, updated.Username);
|
|
|
|
|
Assert.Equal(u.PasswordHash, updated.PasswordHash);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── UDT-008: WithNewPasswordHash ─────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void WithNewPasswordHash_Returns_NewInstance()
|
|
|
|
|
{
|
|
|
|
|
var u = MakeUsuario();
|
2026-04-18 10:12:32 -03:00
|
|
|
var updated = u.WithNewPasswordHash("newhash", mustChangePassword: false, DateTime.UtcNow);
|
2026-04-15 17:36:46 -03:00
|
|
|
Assert.NotSame(u, updated);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void WithNewPasswordHash_Sets_Hash_And_MustChange()
|
|
|
|
|
{
|
|
|
|
|
var u = MakeUsuario();
|
2026-04-18 10:12:32 -03:00
|
|
|
var updated = u.WithNewPasswordHash("newhash", mustChangePassword: true, DateTime.UtcNow);
|
2026-04-15 17:36:46 -03:00
|
|
|
Assert.Equal("newhash", updated.PasswordHash);
|
|
|
|
|
Assert.True(updated.MustChangePassword);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void WithNewPasswordHash_Clears_MustChange_When_False()
|
|
|
|
|
{
|
|
|
|
|
var u = MakeUsuario(mustChangePassword: true);
|
2026-04-18 10:12:32 -03:00
|
|
|
var updated = u.WithNewPasswordHash("hash2", mustChangePassword: false, DateTime.UtcNow);
|
2026-04-15 17:36:46 -03:00
|
|
|
Assert.False(updated.MustChangePassword);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void WithNewPasswordHash_Sets_FechaModificacion()
|
|
|
|
|
{
|
|
|
|
|
var before = DateTime.UtcNow.AddSeconds(-1);
|
2026-04-18 10:12:32 -03:00
|
|
|
var now = DateTime.UtcNow;
|
2026-04-15 17:36:46 -03:00
|
|
|
var u = MakeUsuario();
|
2026-04-18 10:12:32 -03:00
|
|
|
var updated = u.WithNewPasswordHash("hash2", false, now);
|
2026-04-15 17:36:46 -03:00
|
|
|
Assert.NotNull(updated.FechaModificacion);
|
|
|
|
|
Assert.True(updated.FechaModificacion >= before);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── UDT-008: WithUltimoLogin ──────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void WithUltimoLogin_Returns_NewInstance()
|
|
|
|
|
{
|
|
|
|
|
var u = MakeUsuario();
|
|
|
|
|
var updated = u.WithUltimoLogin(DateTime.UtcNow);
|
|
|
|
|
Assert.NotSame(u, updated);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void WithUltimoLogin_Sets_UltimoLogin()
|
|
|
|
|
{
|
|
|
|
|
var ts = new DateTime(2026, 1, 15, 10, 0, 0, DateTimeKind.Utc);
|
|
|
|
|
var u = MakeUsuario();
|
|
|
|
|
var updated = u.WithUltimoLogin(ts);
|
|
|
|
|
Assert.Equal(ts, updated.UltimoLogin);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void WithUltimoLogin_Does_NOT_Touch_FechaModificacion()
|
|
|
|
|
{
|
|
|
|
|
var u = MakeUsuario();
|
|
|
|
|
var originalFecha = u.FechaModificacion;
|
|
|
|
|
var updated = u.WithUltimoLogin(DateTime.UtcNow);
|
|
|
|
|
Assert.Equal(originalFecha, updated.FechaModificacion);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── UDT-008: WithMustChangePassword ──────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void WithMustChangePassword_Sets_Value_True()
|
|
|
|
|
{
|
|
|
|
|
var u = MakeUsuario(mustChangePassword: false);
|
2026-04-18 10:12:32 -03:00
|
|
|
var updated = u.WithMustChangePassword(true, DateTime.UtcNow);
|
2026-04-15 17:36:46 -03:00
|
|
|
Assert.True(updated.MustChangePassword);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void WithMustChangePassword_Sets_FechaModificacion()
|
|
|
|
|
{
|
|
|
|
|
var before = DateTime.UtcNow.AddSeconds(-1);
|
2026-04-18 10:12:32 -03:00
|
|
|
var now = DateTime.UtcNow;
|
2026-04-15 17:36:46 -03:00
|
|
|
var u = MakeUsuario();
|
2026-04-18 10:12:32 -03:00
|
|
|
var updated = u.WithMustChangePassword(true, now);
|
2026-04-15 17:36:46 -03:00
|
|
|
Assert.NotNull(updated.FechaModificacion);
|
|
|
|
|
Assert.True(updated.FechaModificacion >= before);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── helpers ───────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
private static Usuario MakeUsuario(bool mustChangePassword = false)
|
|
|
|
|
=> new(
|
|
|
|
|
id: 1,
|
|
|
|
|
username: "testuser",
|
|
|
|
|
passwordHash: "$2a$12$hash",
|
|
|
|
|
nombre: "Test",
|
|
|
|
|
apellido: "User",
|
|
|
|
|
email: "test@x.com",
|
|
|
|
|
rol: "admin",
|
|
|
|
|
permisosJson: "[]",
|
|
|
|
|
activo: true,
|
|
|
|
|
fechaModificacion: null,
|
|
|
|
|
ultimoLogin: null,
|
|
|
|
|
mustChangePassword: mustChangePassword
|
|
|
|
|
);
|
2026-04-13 21:36:09 -03:00
|
|
|
}
|