using FluentAssertions; using Nalu.Api.PostProcessors; using Nalu.Api.Services; using Xunit; namespace Nalu.Tests; // ── ValidateCpfDigit ────────────────────────────────────────────────────────── public class ValidateCpfDigitTests { private readonly ValidateCpfDigit _sut = new(); [Theory] [InlineData("529.982.247-25", "529.982.247-25")] // valid CPF [InlineData("52998224725", "529.982.247-25")] // no formatting [InlineData("529 982 247 25", "529.982.247-25")] // spaces public void ValidCpf_ReturnsFormattedValue(string input, string expected) { var result = _sut.Process(input); result.IsValid.Should().BeTrue(); result.Value.Should().Be(expected); } [Theory] [InlineData("111.111.111-11")] // all same digit [InlineData("000.000.000-00")] [InlineData("123.456.789-00")] // wrong check digits [InlineData("1234567890")] // too few digits [InlineData("123456789012")] // too many digits public void InvalidCpf_ReturnsInvalid(string input) { var result = _sut.Process(input); result.IsValid.Should().BeFalse(); result.InvalidReason.Should().NotBeNullOrEmpty(); } } // ── FormatPhone ─────────────────────────────────────────────────────────────── public class FormatPhoneTests { private readonly FormatPhone _sut = new(); [Theory] [InlineData("11999998888", "(11) 99999-8888")] // mobile, no formatting [InlineData("(11) 99999-8888", "(11) 99999-8888")] // already formatted [InlineData("+55 11 99999-8888", "(11) 99999-8888")] // with country code [InlineData("1134567890", "(11) 3456-7890")] // landline public void ValidPhone_ReturnsFormatted(string input, string expected) { var result = _sut.Process(input); result.IsValid.Should().BeTrue(); result.Value.Should().Be(expected); } [Theory] [InlineData("9999")] // too short [InlineData("999999999999999")] // too long [InlineData("1190909090909")] // 13 digits — no valid Brazilian format [InlineData("23999998888")] // invalid DDD 23 [InlineData("36999998888")] // invalid DDD 36 [InlineData("52999998888")] // invalid DDD 52 public void InvalidPhone_ReturnsInvalid(string input) { var result = _sut.Process(input); result.IsValid.Should().BeFalse(); } } // ── FormatCep ───────────────────────────────────────────────────────────────── public class FormatCepTests { private readonly FormatCep _sut = new(); [Theory] [InlineData("01001000", "01001-000")] [InlineData("01001-000", "01001-000")] [InlineData("04538133", "04538-133")] public void ValidCep_ReturnsFormatted(string input, string expected) { var result = _sut.Process(input); result.IsValid.Should().BeTrue(); result.Value.Should().Be(expected); } [Theory] [InlineData("0000000")] // 7 digits [InlineData("000000000")] // 9 digits [InlineData("00000000")] // all zeros public void InvalidCep_ReturnsInvalid(string input) { var result = _sut.Process(input); result.IsValid.Should().BeFalse(); } } // ── CorrectEmailTypos ───────────────────────────────────────────────────────── public class CorrectEmailTyposTests { private readonly CorrectEmailTypos _sut = new(); [Theory] [InlineData("user@gamil.com", "user@gmail.com", "user@gamil.com")] [InlineData("user@gmaill.com", "user@gmail.com", "user@gmaill.com")] [InlineData("user@hotmal.com", "user@hotmail.com", "user@hotmal.com")] [InlineData("user@outlok.com", "user@outlook.com", "user@outlok.com")] [InlineData("user@yaho.com", "user@yahoo.com", "user@yaho.com")] public void TypoDomain_ReturnsCorrected(string input, string expectedValue, string expectedOriginal) { var result = _sut.Process(input); result.IsValid.Should().BeTrue(); result.WasCorrected.Should().BeTrue(); result.Value.Should().Be(expectedValue); result.OriginalValue.Should().Be(expectedOriginal); } [Theory] [InlineData("user@gmail.com")] [InlineData("user@hotmail.com")] [InlineData("user@company.com.br")] public void CorrectDomain_ReturnsOk_NotCorrected(string input) { var result = _sut.Process(input); result.IsValid.Should().BeTrue(); result.WasCorrected.Should().BeFalse(); } } // ── DeterministicLayer — new validators ─────────────────────────────────────── public class CpfDeterministicTests { private readonly DeterministicLayer _layer = new(); [Fact] public void CpfPattern_ExtractsDigits() { var validator = ValidatorLoader.ParseFromContent("validate_cpf", System.IO.File.ReadAllText("../../../../../src/Nalu.Api/Validators/validate_cpf.md")); var result = _layer.Evaluate(validator, "123.456.789-09"); result.Outcome.Should().Be(DeterministicOutcome.Accepted); result.ExtractedValue.Should().Contain("12345678909"); } [Fact] public void CpfEvasive_ReturnsRejected() { var validator = ValidatorLoader.ParseFromContent("validate_cpf", System.IO.File.ReadAllText("../../../../../src/Nalu.Api/Validators/validate_cpf.md")); var result = _layer.Evaluate(validator, "não lembro"); result.Outcome.Should().Be(DeterministicOutcome.Rejected); } }