Some checks failed
NALU Deployment Pipeline / Run Tests (push) Successful in 4m16s
NALU Deployment Pipeline / PR Validation (push) Has been skipped
NALU Deployment Pipeline / Build and Push Image (push) Failing after 13s
NALU Deployment Pipeline / Deploy naluai.dev (push) Has been skipped
NALU Deployment Pipeline / Cleanup Old Resources (push) Has been skipped
- DeterministicLayer: accept patterns now use IgnoreCase (was None) - Test: CPF ExtractedValue is raw formatted match, not stripped digits - CI filter: also exclude McpServerTests (require live server) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
169 lines
6.0 KiB
C#
169 lines
6.0 KiB
C#
using FluentAssertions;
|
|
using Nalu.Web.PostProcessors;
|
|
using Nalu.Web.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().Be("123.456.789-09"); // raw match; postprocessor strips punctuation
|
|
}
|
|
|
|
[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);
|
|
}
|
|
}
|