Some checks failed
NALU Deployment Pipeline / Run Tests (push) Failing after 2m29s
NALU Deployment Pipeline / PR Validation (push) Has been skipped
NALU Deployment Pipeline / Build and Push Image (push) Has been skipped
NALU Deployment Pipeline / Deploy naluai.dev (push) Has been skipped
NALU Deployment Pipeline / Cleanup Old Resources (push) Has been skipped
- Test project was referencing non-existent Nalu.Api.csproj → Nalu.Web.csproj - Replace using Nalu.Api.* → Nalu.Web.* in all test files - Skip PipelineIntegration tests in CI (require live MongoDB) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
134 lines
4.7 KiB
C#
134 lines
4.7 KiB
C#
using FluentAssertions;
|
|
using Nalu.Web.Models;
|
|
using Nalu.Web.Services;
|
|
using Xunit;
|
|
|
|
namespace Nalu.Tests;
|
|
|
|
public class DeterministicLayerTests
|
|
{
|
|
private readonly DeterministicLayer _layer = new();
|
|
|
|
private static ValidatorDefinition NameValidator() => new ValidatorDefinition
|
|
{
|
|
Id = "validate_full_name",
|
|
StopWords = ["bom dia", "boa tarde", "boa noite", "olá", "oi"],
|
|
RejectPatterns =
|
|
[
|
|
@"^(não|nao|sei la|sei lá|tanto faz)$",
|
|
@"^\d+$"
|
|
],
|
|
AcceptPatterns =
|
|
[
|
|
@"^meu nome é\s+(.+)$",
|
|
@"^me chamo\s+(.+)$"
|
|
],
|
|
Constraints = new Dictionary<string, string>
|
|
{
|
|
{ "min_length", "2" },
|
|
{ "must_have_alpha", "true" },
|
|
{ "max_length", "120" }
|
|
}
|
|
};
|
|
|
|
// ── Stop words ────────────────────────────────────────────────────────────
|
|
|
|
[Theory]
|
|
[InlineData("Bom dia")]
|
|
[InlineData("bom dia")]
|
|
[InlineData("Bom dia!")]
|
|
[InlineData("Oi")]
|
|
[InlineData("olá")]
|
|
public void StopWord_ReturnsRejected(string input)
|
|
{
|
|
var result = _layer.Evaluate(NameValidator(), input);
|
|
|
|
result.Outcome.Should().Be(DeterministicOutcome.Rejected);
|
|
result.ExtractedValue.Should().BeNull();
|
|
}
|
|
|
|
// ── Reject patterns ───────────────────────────────────────────────────────
|
|
|
|
[Theory]
|
|
[InlineData("não")]
|
|
[InlineData("sei la")]
|
|
[InlineData("tanto faz")]
|
|
[InlineData("12345")]
|
|
public void RejectPattern_ReturnsRejected(string input)
|
|
{
|
|
var result = _layer.Evaluate(NameValidator(), input);
|
|
|
|
result.Outcome.Should().Be(DeterministicOutcome.Rejected);
|
|
}
|
|
|
|
// ── Accept patterns ───────────────────────────────────────────────────────
|
|
|
|
[Theory]
|
|
[InlineData("meu nome é João Silva", "João Silva")]
|
|
[InlineData("Meu nome é Maria", "Maria")]
|
|
[InlineData("me chamo Pedro", "Pedro")]
|
|
public void AcceptPattern_ReturnsAcceptedWithCapturedGroup(string input, string expectedValue)
|
|
{
|
|
var result = _layer.Evaluate(NameValidator(), input);
|
|
|
|
result.Outcome.Should().Be(DeterministicOutcome.Accepted);
|
|
result.ExtractedValue.Should().Be(expectedValue);
|
|
}
|
|
|
|
// ── Unresolved ────────────────────────────────────────────────────────────
|
|
|
|
[Theory]
|
|
[InlineData("Carlos Alberto Ferreira")]
|
|
[InlineData("Ana")]
|
|
public void FreeText_ReturnsUnresolved(string input)
|
|
{
|
|
var result = _layer.Evaluate(NameValidator(), input);
|
|
|
|
result.Outcome.Should().Be(DeterministicOutcome.Unresolved);
|
|
}
|
|
|
|
// ── Constraints ───────────────────────────────────────────────────────────
|
|
|
|
[Fact]
|
|
public void AcceptPattern_WhenValueTooShort_ReturnsConstraintFailed()
|
|
{
|
|
var validator = NameValidator();
|
|
validator.Constraints["min_length"] = "5";
|
|
|
|
var result = _layer.Evaluate(validator, "meu nome é Al");
|
|
|
|
result.Outcome.Should().Be(DeterministicOutcome.ConstraintFailed);
|
|
result.Reasoning.Should().Contain("mínimo");
|
|
}
|
|
|
|
[Fact]
|
|
public void AcceptPattern_WhenValueHasNoLetters_ReturnsConstraintFailed()
|
|
{
|
|
var result = _layer.Evaluate(NameValidator(), "meu nome é 999");
|
|
|
|
result.Outcome.Should().Be(DeterministicOutcome.ConstraintFailed);
|
|
result.Reasoning.Should().Contain("letras");
|
|
}
|
|
|
|
[Fact]
|
|
public void AcceptPattern_WhenValueTooLong_ReturnsConstraintFailed()
|
|
{
|
|
var longName = new string('A', 121);
|
|
var result = _layer.Evaluate(NameValidator(), $"meu nome é {longName}");
|
|
|
|
result.Outcome.Should().Be(DeterministicOutcome.ConstraintFailed);
|
|
result.Reasoning.Should().Contain("máximo");
|
|
}
|
|
|
|
// ── No patterns configured ────────────────────────────────────────────────
|
|
|
|
[Fact]
|
|
public void EmptyValidator_AlwaysUnresolved()
|
|
{
|
|
var validator = new ValidatorDefinition { Id = "empty" };
|
|
var result = _layer.Evaluate(validator, "qualquer coisa");
|
|
|
|
result.Outcome.Should().Be(DeterministicOutcome.Unresolved);
|
|
}
|
|
}
|