using FluentAssertions; using Microsoft.Extensions.Time.Testing; using SIGCM2.Domain.Entities; namespace SIGCM2.Application.Tests.Domain.Rubros; public class RubroTests { private static readonly FakeTimeProvider FakeTime = new(new DateTimeOffset(2026, 4, 18, 12, 0, 0, TimeSpan.Zero)); // ── ForCreation: happy path ────────────────────────────────────────────── [Fact] public void Create_con_datos_validos_crea_rubro_activo_con_orden_cero_como_default() { var rubro = Rubro.ForCreation("Autos", parentId: null, orden: 0, tarifarioBaseId: null, FakeTime); rubro.Nombre.Should().Be("Autos"); rubro.ParentId.Should().BeNull(); rubro.Orden.Should().Be(0); rubro.Activo.Should().BeTrue(); rubro.TarifarioBaseId.Should().BeNull(); rubro.Id.Should().Be(0); rubro.FechaCreacion.Should().Be(FakeTime.GetUtcNow().UtcDateTime); rubro.FechaModificacion.Should().BeNull(); } [Fact] public void Create_root_con_parentId_null_es_valido() { var rubro = Rubro.ForCreation("Autos", parentId: null, orden: 0, tarifarioBaseId: null, FakeTime); rubro.ParentId.Should().BeNull(); } // ── ForCreation: validations ───────────────────────────────────────────── [Fact] public void Create_con_nombre_vacio_lanza_ArgumentException() { var act = () => Rubro.ForCreation("", parentId: null, orden: 0, tarifarioBaseId: null, FakeTime); act.Should().Throw(); } [Fact] public void Create_con_nombre_solo_whitespace_lanza_ArgumentException() { var act = () => Rubro.ForCreation(" ", parentId: null, orden: 0, tarifarioBaseId: null, FakeTime); act.Should().Throw(); } [Fact] public void Create_con_nombre_excediendo_200_chars_lanza_ArgumentException() { var nombre = new string('A', 201); var act = () => Rubro.ForCreation(nombre, parentId: null, orden: 0, tarifarioBaseId: null, FakeTime); act.Should().Throw(); } [Fact] public void Create_con_parentId_menor_o_igual_a_cero_lanza_ArgumentException() { var act = () => Rubro.ForCreation("Autos", parentId: 0, orden: 0, tarifarioBaseId: null, FakeTime); act.Should().Throw(); } [Fact] public void Create_con_tarifarioBaseId_menor_a_cero_lanza_ArgumentException() { var act = () => Rubro.ForCreation("Autos", parentId: null, orden: 0, tarifarioBaseId: -1, FakeTime); act.Should().Throw(); } // ── WithRenamed ────────────────────────────────────────────────────────── [Fact] public void Rename_con_nombre_valido_devuelve_nueva_instancia_con_FechaModificacion() { var rubro = Rubro.ForCreation("Autos", parentId: null, orden: 0, tarifarioBaseId: null, FakeTime); var laterTime = new FakeTimeProvider(new DateTimeOffset(2026, 4, 18, 14, 0, 0, TimeSpan.Zero)); var renamed = rubro.WithRenamed("Vehiculos", laterTime); renamed.Nombre.Should().Be("Vehiculos"); renamed.FechaModificacion.Should().Be(laterTime.GetUtcNow().UtcDateTime); } [Fact] public void Rename_con_nombre_invalido_lanza_ArgumentException() { var rubro = Rubro.ForCreation("Autos", parentId: null, orden: 0, tarifarioBaseId: null, FakeTime); var act = () => rubro.WithRenamed("", FakeTime); act.Should().Throw(); } [Fact] public void Rename_no_muta_la_instancia_original() { var rubro = Rubro.ForCreation("Autos", parentId: null, orden: 0, tarifarioBaseId: null, FakeTime); rubro.WithRenamed("Vehiculos", FakeTime); rubro.Nombre.Should().Be("Autos"); } // ── WithMoved ──────────────────────────────────────────────────────────── [Fact] public void Move_a_nuevo_parent_devuelve_nueva_instancia_con_parentId_actualizado() { var rubro = Rubro.ForCreation("Autos", parentId: null, orden: 0, tarifarioBaseId: null, FakeTime); var moved = rubro.WithMoved(nuevoParentId: 5, nuevoOrden: 2, FakeTime); moved.ParentId.Should().Be(5); moved.Orden.Should().Be(2); } [Fact] public void Move_a_root_permite_parentId_null() { var rubro = Rubro.ForCreation("Autos", parentId: 3, orden: 0, tarifarioBaseId: null, FakeTime); var moved = rubro.WithMoved(nuevoParentId: null, nuevoOrden: 0, FakeTime); moved.ParentId.Should().BeNull(); } [Fact] public void Move_no_muta_la_instancia_original() { var rubro = Rubro.ForCreation("Autos", parentId: null, orden: 0, tarifarioBaseId: null, FakeTime); rubro.WithMoved(nuevoParentId: 5, nuevoOrden: 1, FakeTime); rubro.ParentId.Should().BeNull(); rubro.Orden.Should().Be(0); } // ── WithActivo (Deactivate / Reactivate) ──────────────────────────────── [Fact] public void Deactivate_flip_Activo_a_false() { var rubro = Rubro.ForCreation("Autos", parentId: null, orden: 0, tarifarioBaseId: null, FakeTime); var deactivated = rubro.WithActivo(false, FakeTime); deactivated.Activo.Should().BeFalse(); deactivated.FechaModificacion.Should().Be(FakeTime.GetUtcNow().UtcDateTime); } [Fact] public void Reactivate_flip_Activo_a_true() { var rubro = Rubro.ForCreation("Autos", parentId: null, orden: 0, tarifarioBaseId: null, FakeTime); var deactivated = rubro.WithActivo(false, FakeTime); var reactivated = deactivated.WithActivo(true, FakeTime); reactivated.Activo.Should().BeTrue(); } }