using FluentAssertions; using SIGCM2.Domain.Exceptions; using SIGCM2.Domain.Pricing.Exceptions; namespace SIGCM2.Application.Tests.Domain.Pricing.Exceptions; /// /// PRC-001 — T2.1 Domain unit tests for Pricing exceptions. /// Verifies constructor props, message content, and DomainException inheritance. /// public sealed class PricingExceptionTests { // ── EmojiDetectedException ──────────────────────────────────────────────── [Fact] public void EmojiDetectedException_SetsDetectedCodepoint() { var ex = new EmojiDetectedException(0x1F697); // 🚗 ex.DetectedCodepoint.Should().Be(0x1F697); } [Fact] public void EmojiDetectedException_MessageContainsCodepoint() { var ex = new EmojiDetectedException(0x1F697); ex.Message.Should().NotBeNullOrWhiteSpace(); } [Fact] public void EmojiDetectedException_InheritsFromDomainException() { var ex = new EmojiDetectedException(0x1F697); ex.Should().BeAssignableTo(); } // ── WordCountValidationException ───────────────────────────────────────── [Fact] public void WordCountValidationException_SetsFieldAndReason() { var ex = new WordCountValidationException("rawText", "El texto supera el máximo de 2000 caracteres."); ex.Field.Should().Be("rawText"); ex.Reason.Should().Be("El texto supera el máximo de 2000 caracteres."); } [Fact] public void WordCountValidationException_MessageContainsFieldAndReason() { var ex = new WordCountValidationException("rawText", "supera el máximo"); ex.Message.Should().Contain("rawText"); ex.Message.Should().Contain("supera el máximo"); } [Fact] public void WordCountValidationException_InheritsFromDomainException() { var ex = new WordCountValidationException("field", "reason"); ex.Should().BeAssignableTo(); } // ── ChargeableCharConfigInvalidException ───────────────────────────────── [Fact] public void ChargeableCharConfigInvalidException_SetsFieldAndReason() { var ex = new ChargeableCharConfigInvalidException("PricePerUnit", "debe ser > 0"); ex.Field.Should().Be("PricePerUnit"); ex.Reason.Should().Be("debe ser > 0"); } [Fact] public void ChargeableCharConfigInvalidException_MessageContainsFieldAndReason() { var ex = new ChargeableCharConfigInvalidException("Symbol", "no puede estar vacío"); ex.Message.Should().Contain("Symbol"); ex.Message.Should().Contain("no puede estar vacío"); } [Fact] public void ChargeableCharConfigInvalidException_InheritsFromDomainException() { var ex = new ChargeableCharConfigInvalidException("field", "reason"); ex.Should().BeAssignableTo(); } // ── ChargeableCharConfigForwardOnlyException ────────────────────────────── [Fact] public void ChargeableCharConfigForwardOnlyException_SetsAllProperties() { var newVf = new DateOnly(2026, 3, 1); var activeVf = new DateOnly(2026, 4, 1); var ex = new ChargeableCharConfigForwardOnlyException( productTypeId: 5, symbol: "$", newValidFrom: newVf, activeValidFrom: activeVf); ex.ProductTypeId.Should().Be(5); ex.Symbol.Should().Be("$"); ex.NewValidFrom.Should().Be(newVf); ex.ActiveValidFrom.Should().Be(activeVf); } [Fact] public void ChargeableCharConfigForwardOnlyException_NullProductTypeId_IsAllowed() { var ex = new ChargeableCharConfigForwardOnlyException( productTypeId: null, symbol: "$", newValidFrom: new DateOnly(2026, 3, 1), activeValidFrom: new DateOnly(2026, 4, 1)); ex.ProductTypeId.Should().BeNull(); } [Fact] public void ChargeableCharConfigForwardOnlyException_MessageContainsKeyDates() { var newVf = new DateOnly(2026, 3, 1); var activeVf = new DateOnly(2026, 4, 1); var ex = new ChargeableCharConfigForwardOnlyException( productTypeId: null, symbol: "$", newValidFrom: newVf, activeValidFrom: activeVf); ex.Message.Should().Contain("2026-03-01"); ex.Message.Should().Contain("2026-04-01"); } [Fact] public void ChargeableCharConfigForwardOnlyException_InheritsFromDomainException() { var ex = new ChargeableCharConfigForwardOnlyException( productTypeId: null, symbol: "$", newValidFrom: new DateOnly(2026, 3, 1), activeValidFrom: new DateOnly(2026, 4, 1)); ex.Should().BeAssignableTo(); } }