Skip to content

Commit c218ea6

Browse files
committed
Refactor and expand tests; improve RuleSet metadata
Test suite refactored and expanded; RuleSet metadata and error reporting improved - Test suite reorganization and expansion -- Split BuildInPredicates tests into topic-based files under RoyalCode.SmartValidations.Tests.Predicates. -- Deleted monolithic test files; replaced with granular, focused test files. -- Moved BuildInRulesTests to new namespace/file. -- Added comprehensive RuleSet tests under RoyalCode.SmartValidations.Tests.RuleSetRules, covering all rules, property/display name resolution, and extension metadata. -- Added file-scoped helper classes for display name/property resolution in tests. -- Reformatted test project file for consistency. -- Updated solution file to include README.md. -- Replaced empty BuildInPredicatesTests.StringsAndPattern.cs with a stub in the new namespace. - RuleSet struct improvements -- Added public GetPropertyNameAndDisplayName for testability and internal use. -- Refactored LessThan, LessThanOrEqual, GreaterThan, GreaterThanOrEqual, Email, and Url rules to use a new WithProblem overload with rule name and value metadata. -- Added private WithCustomProblem overloads to DRY up Must/BothMust and custom rule error reporting, ensuring rule name and value metadata are attached. -- Fixed Nested to use 1-based indexing for collection property names. - Rules static class updates -- Added constant rule names for LessThan, LessThanOrEqual, GreaterThan, GreaterThanOrEqual, Email, and Url for use in extension metadata. - Documentation and organization -- Updated README.md with improved formatting, more examples, and clearer explanations (in Portuguese). These changes provide more comprehensive and maintainable test coverage, improved RuleSet testability, and richer extension metadata for validation errors.
1 parent a2b0242 commit c218ea6

27 files changed

Lines changed: 2204 additions & 156 deletions

README.md

Lines changed: 141 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,142 @@
11
# SmartValidations
2-
A validation framework build on top of SmartProblems
2+
3+
Biblioteca de validação fluente para .NET, construída sobre SmartProblems, focada em validar propriedades de modelos (especialmente DTOs/requests) e produzir `Problems` quando regras falham.
4+
5+
Objetivo
6+
- Validar propriedades de um modelo em uma única passagem usando um `RuleSet`.
7+
- Retornar `Problems` via integração com SmartProblems (Problem, Problems, Result), sem lançar exceções.
8+
- Facilitar validações aninhadas (objetos e coleções) e compor regras de forma fluente.
9+
10+
Targets e requisitos
11+
- .NET 8, .NET 9, .NET 10.
12+
- C# 12+ com uso de `CallerArgumentExpression` e genéricos com `INumber<T>`.
13+
- Depende de SmartProblems para agregar e enriquecer erros.
14+
15+
Instalação
16+
- Adicione SmartValidations e SmartProblems ao seu projeto (NuGet quando disponível).
17+
18+
Conceitos principais
19+
- `Rules.Set()` / `Rules.Set<T>()`: cria um `RuleSet` para aplicar regras.
20+
- `RuleSet`: DSL fluente que acumula `Problems` quando validações falham.
21+
- `BuildInPredicates`: funções utilitárias usadas internamente pelas regras.
22+
- `IValidable` e `ValidateFunc`: pontos de integração para validações aninhadas.
23+
24+
Uso básico
25+
```csharp
26+
public class CreateOrderRequest
27+
{
28+
public string CustomerName { get; set; } = string.Empty;
29+
public decimal TotalAmount { get; set; }
30+
31+
public bool HasProblems(out Problems? problems)
32+
{
33+
return Rules.Set<CreateOrderRequest>()
34+
.NotEmpty(CustomerName)
35+
.GreaterThan(TotalAmount, 0)
36+
.HasProblems(out problems);
37+
}
38+
}
39+
```
40+
41+
Validações de strings e padrões
42+
```csharp
43+
Rules.Set()
44+
.NotEmpty(Name)
45+
.MinLength(Name, 3)
46+
.MaxLength(Name, 100)
47+
.OnlyLettersOrDigits(Username)
48+
.NoWhiteSpace(Username)
49+
.Matches(Email, @"^.+@.+\..+$", "email pattern")
50+
.Email(Email)
51+
.Url(Website)
52+
.HasProblems(out var problems);
53+
```
54+
55+
Comparações e limites
56+
```csharp
57+
Rules.Set()
58+
.Equal(Code, "ABC", StringComparison.OrdinalIgnoreCase)
59+
.NotEqual(Status, "inactive")
60+
.Min(Age, 18)
61+
.Max(ItemsCount, 100)
62+
.MinMax(Score, 0, 100)
63+
.LessThan(StartDate, EndDate)
64+
.GreaterThanOrEqual(Quantity, 1)
65+
.HasProblems(out var problems);
66+
```
67+
68+
Regras customizadas (`Must`)
69+
```csharp
70+
Rules.Set()
71+
.Must(Password, p => p.Length >= 8 && p.Any(char.IsDigit),
72+
(prop, val) => $"{prop} must contain at least 8 chars and a digit.")
73+
.BothMust(Start, End, (s, e) => s < e,
74+
(p1, p2, v1, v2) => $"{p1} must be before {p2}.")
75+
.HasProblems(out var problems);
76+
```
77+
78+
Validações aninhadas (objetos)
79+
```csharp
80+
public class Order : IValidable
81+
{
82+
public string CustomerName { get; set; } = string.Empty;
83+
public decimal TotalAmount { get; set; }
84+
public Address? ShippingAddress { get; set; }
85+
86+
public bool HasProblems(out Problems? problems)
87+
{
88+
return Rules.Set<Order>()
89+
.NotEmpty(CustomerName)
90+
.GreaterThan(TotalAmount, 0)
91+
.NotNullNested(ShippingAddress, address => Rules.Set<Address>()
92+
.WithPropertyPrefix("address")
93+
.NotEmpty(address.Street)
94+
.NotEmpty(address.City)
95+
.NotEmpty(address.ZipCode)
96+
.NotEmpty(address.Country))
97+
.HasProblems(out problems);
98+
}
99+
}
100+
```
101+
102+
Validações aninhadas (coleções)
103+
```csharp
104+
public class OrderColl : IValidable
105+
{
106+
public List<Address>? Addresses { get; set; }
107+
108+
public bool HasProblems(out Problems? problems)
109+
{
110+
return Rules.Set<OrderColl>()
111+
.Nested(Addresses, address => Rules.Set<Address>()
112+
.WithPropertyPrefix("address")
113+
.NotEmpty(address.Street)
114+
.NotEmpty(address.City)
115+
.NotEmpty(address.ZipCode)
116+
.NotEmpty(address.Country))
117+
.HasProblems(out problems);
118+
}
119+
}
120+
```
121+
122+
Integração com SmartProblems
123+
- Cada regra que falha adiciona um `Problem` via `Problems.InvalidParameter(...)` com metadados:
124+
- `rule`: nome da regra (`Rules.RuleProperty`).
125+
- `current`: valor atual (`Rules.CurrentValueProperty`).
126+
- `expected`: valor(es) esperado(s) (`Rules.ExpectedValueProperty`).
127+
- `pattern`: expressão regular utilizada (`Rules.PatternProperty`).
128+
- O `RuleSet` pode ser convertido implicitamente em `Problems?` ou consultado via `HasProblems(out var problems)`.
129+
130+
Nomes de propriedades e prefixos
131+
- `CallerArgumentExpression` captura o nome da propriedade automaticamente.
132+
- `WithPropertyPrefix("prefix")` permite remover o prefixo do nome ao encadear erros de objetos aninhados.
133+
- Coleções incluem índice no encadeamento de propriedade.
134+
135+
Boas práticas
136+
- Concentre a validação em uma função por modelo de entrada (único `RuleSet`).
137+
- Use `IValidable`/`ValidateFunc` para validar agregados e objetos aninhados.
138+
- Prefira mensagens em `R` para internacionalização e consistência.
139+
- Utilize `StringComparison` apropriado em regras de string.
140+
141+
Licença
142+
- Consulte a licença do repositório.

RoyalCode.SmartValidations.Tests/BuildInPredicatesTests.StringsAndPattern.cs

Lines changed: 0 additions & 6 deletions
This file was deleted.

RoyalCode.SmartValidations.Tests/BuildInPredicatesTests.EqualsNotEquals.cs renamed to RoyalCode.SmartValidations.Tests/Predicates/BuildInPredicatesTests.EqualsNotEquals.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using System.Numerics;
22

3-
namespace RoyalCode.SmartValidations.Tests;
3+
namespace RoyalCode.SmartValidations.Tests.Predicates;
44

55
public partial class BuildInPredicatesTests
66
{

RoyalCode.SmartValidations.Tests/BuildInPredicatesTests.LessGreater.cs renamed to RoyalCode.SmartValidations.Tests/Predicates/BuildInPredicatesTests.LessGreater.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace RoyalCode.SmartValidations.Tests;
1+
namespace RoyalCode.SmartValidations.Tests.Predicates;
22

33
public partial class BuildInPredicatesTests
44
{

RoyalCode.SmartValidations.Tests/BuildInPredicatesTests.MinMax.cs renamed to RoyalCode.SmartValidations.Tests/Predicates/BuildInPredicatesTests.MinMax.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using System.Numerics;
22

3-
namespace RoyalCode.SmartValidations.Tests;
3+
namespace RoyalCode.SmartValidations.Tests.Predicates;
44

55
public partial class BuildInPredicatesTests
66
{

RoyalCode.SmartValidations.Tests/BuildInPredicatesTests.Must.cs renamed to RoyalCode.SmartValidations.Tests/Predicates/BuildInPredicatesTests.Must.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace RoyalCode.SmartValidations.Tests;
1+
namespace RoyalCode.SmartValidations.Tests.Predicates;
22

33
public partial class BuildInPredicatesTests
44
{

RoyalCode.SmartValidations.Tests/BuildInPredicatesTests.NotEmpty.cs renamed to RoyalCode.SmartValidations.Tests/Predicates/BuildInPredicatesTests.NotEmpty.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using System.Numerics;
22

3-
namespace RoyalCode.SmartValidations.Tests;
3+
namespace RoyalCode.SmartValidations.Tests.Predicates;
44

55
public partial class BuildInPredicatesTests
66
{

RoyalCode.SmartValidations.Tests/BuildInPredicatesTests.NullOrNotEmpty.cs renamed to RoyalCode.SmartValidations.Tests/Predicates/BuildInPredicatesTests.NullOrNotEmpty.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using System.Numerics;
22

3-
namespace RoyalCode.SmartValidations.Tests;
3+
namespace RoyalCode.SmartValidations.Tests.Predicates;
44

55
public partial class BuildInPredicatesTests
66
{
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace RoyalCode.SmartValidations.Tests.Predicates;
2+
3+
public partial class BuildInPredicatesTests
4+
{
5+
6+
}

RoyalCode.SmartValidations.Tests/BuildInPredicatesTests.cs renamed to RoyalCode.SmartValidations.Tests/Predicates/BuildInPredicatesTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace RoyalCode.SmartValidations.Tests;
1+
namespace RoyalCode.SmartValidations.Tests.Predicates;
22

33
public partial class BuildInPredicatesTests
44
{

0 commit comments

Comments
 (0)