Skip to content

Commit

Permalink
fix: add tests for nullable
Browse files Browse the repository at this point in the history
  • Loading branch information
wellgenio committed Dec 16, 2024
1 parent fd44bcd commit afcd27e
Show file tree
Hide file tree
Showing 32 changed files with 494 additions and 5 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ Here’s a complete list of available validators you can use:
- **inclusiveBetween**: Checks if the datetime value is between two datetime values, including both bounds.
- **exclusiveBetween**: Checks if the datetime value is between two datetime values, excluding both bounds.

**Observation: for almost all validators, there is an equivalent with the `OrNull` suffix. Example: `validEmailOrNull`**

## Usage with Flutter

If you’re using the `lucid_validation` package in a Flutter app, integrating with `TextFormField` is straightforward.
Expand Down Expand Up @@ -200,7 +202,7 @@ Example:
```dart
ruleFor((user) => user.phoneNumber, key: 'phoneNumber')
.when((user) => user.requiresPhoneNumber)
.must((value) => value.isNotEmpty, 'Phone number is required', 'phone_required')
.isEmpty()
.must((value) => value.length == 10, 'Phone number must be 10 digits', 'phone_length');
```

Expand Down
2 changes: 1 addition & 1 deletion example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ packages:
path: ".."
relative: true
source: path
version: "1.0.1"
version: "1.1.0"
matcher:
dependency: transitive
description:
Expand Down
4 changes: 2 additions & 2 deletions lib/src/validations/is_not_null_validation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ part of 'validations.dart';
///
/// This extension adds an `isNotNull` method that can be used to ensure that a value
/// is not null.
extension IsNotNullValidation<T> on SimpleValidationBuilder<T?> {
extension IsNotNullValidation<T extends Object> on SimpleValidationBuilder<T?> {
/// Adds a validation rule that checks if the value is not null.
///
/// [message] is the error message returned if the validation fails.
Expand All @@ -22,7 +22,7 @@ extension IsNotNullValidation<T> on SimpleValidationBuilder<T?> {
/// String format args:
/// - **{PropertyName}**: The name of the property.
///
SimpleValidationBuilder<String> isNotNull({String? message, String? code}) {
SimpleValidationBuilder<T> isNotNull({String? message, String? code}) {
return useNotNull(
(value, entity) {
if (value != null) return null;
Expand Down
93 changes: 93 additions & 0 deletions lib/src/validations/range_validation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,96 @@ extension RangeValidation on SimpleValidationBuilder<num> {
);
}
}

extension RangeNullableValidation on SimpleValidationBuilder<num?> {
/// Adds a validation rule that checks if the [num?] is within the range of [min] and [max].
///
/// [min] and [max] define the acceptable range for the number.
/// [message] is the error message returned if the validation fails. Defaults to "Must be between $min and $max".
/// [code] is an optional error code for translation purposes.
///
/// Returns the [LucidValidationBuilder] to allow for method chaining.
///
/// Example:
/// ```dart
/// ...
/// ruleFor((user) => user.age, key: 'age') // user.age is nullable
/// .range(18, 65);
/// ```
///
/// String format args:
/// - **{PropertyName}**: The name of the property.
/// - **{From}**: The minimum value of the range.
/// - **{To}**: The maximum value of the range.
/// - **{PropertyValue}**: The value of the property.
///
SimpleValidationBuilder<num?> range(num min, num max,
{String? message, String? code}) {
return use(
(value, entity) {
if (value != null && value >= min && value <= max) return null;

final currentCode = code ?? Language.code.range;
final currentMessage = LucidValidation.global.languageManager.translate(
currentCode,
parameters: {
'PropertyName': label.isNotEmpty ? label : key,
'From': '$min',
'To': '$max',
'PropertyValue': '$value',
},
defaultMessage: message,
);

return ValidationException(message: currentMessage, code: currentCode);
},
);
}
}

extension RangeOrNullableValidation on SimpleValidationBuilder<num?> {
/// Adds a validation rule that checks if the [num?] is within the range of [min] and [max].
///
/// [min] and [max] define the acceptable range for the number.
/// [message] is the error message returned if the validation fails. Defaults to "Must be between $min and $max".
/// [code] is an optional error code for translation purposes.
///
/// Returns the [LucidValidationBuilder] to allow for method chaining.
///
/// Example:
/// ```dart
/// ...
/// ruleFor((user) => user.age, key: 'age') // user.age is nullable
/// .range(18, 65);
/// ```
///
/// String format args:
/// - **{PropertyName}**: The name of the property.
/// - **{From}**: The minimum value of the range.
/// - **{To}**: The maximum value of the range.
/// - **{PropertyValue}**: The value of the property.
///
SimpleValidationBuilder<num?> rangeOrNull(num min, num max,
{String? message, String? code}) {
return use(
(value, entity) {
if (value == null) return null;
if (value >= min && value <= max) return null;

final currentCode = code ?? Language.code.range;
final currentMessage = LucidValidation.global.languageManager.translate(
currentCode,
parameters: {
'PropertyName': label.isNotEmpty ? label : key,
'From': '$min',
'To': '$max',
'PropertyValue': '$value',
},
defaultMessage: message,
);

return ValidationException(message: currentMessage, code: currentCode);
},
);
}
}
3 changes: 2 additions & 1 deletion lib/src/validations/valid_cep_validation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,9 @@ extension ValidCEPNullableValidation on SimpleValidationBuilder<String?> {
///
SimpleValidationBuilder<String?> validCEP({String? message, String? code}) {
return use((value, entity) {
if (value != null && RegExp(r'^\d{5}-?\d{3}$').hasMatch(value))
if (value != null && RegExp(r'^\d{5}-?\d{3}$').hasMatch(value)) {
return null;
}

final currentCode = code ?? Language.code.validCEP;
final currentMessage = LucidValidation.global.languageManager.translate(
Expand Down
31 changes: 31 additions & 0 deletions test/mocks/mocks.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ class UserModel {
String? cpf = '';
}

class UserNullableModel {
String? email = '';
String? password = '';
String? confirmPassword = '';
String? description;
int? age = 0;
String phone = '';
String? cpf = '';
}

class UserValidator extends LucidValidator<UserModel> {
UserValidator() {
ruleFor((user) => user.email, key: 'email') //
Expand Down Expand Up @@ -107,6 +117,11 @@ class Address {
});
}

class AddressNullable {
String? country;
String? postcode;
}

class AddressValidator extends LucidValidator<Address> {
AddressValidator() {
ruleFor((address) => address.country, key: 'country') //
Expand All @@ -129,6 +144,12 @@ class Customer {
});
}

class CustomerNullable {
String? name;
Address? address;
String? cnpj;
}

class CustomerValidator extends LucidValidator<Customer> {
final addressValidator = AddressValidator();

Expand All @@ -151,10 +172,20 @@ class EventModel {
DateTime dateEvent = DateTime.now();
}

class EventNullableModel {
DateTime? start = DateTime.now();
DateTime? end = DateTime.now();
DateTime? dateEvent = DateTime.now();
}

class CreditCardModel {
String number = '';
}

class CreditCardNullableModel {
String? number;
}

class CreditCardValidator extends LucidValidator<CreditCardModel> {
CreditCardValidator() {
ruleFor((card) => card.number, key: 'number') //
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,22 @@ void main() {

expect(result.isValid, true);
});

test(
'must return valid exclusively between validation when the event date is null',
() {
final validator = TestLucidValidator<EventNullableModel>();
final now = DateTime.now();
final afterTomorrow = now.add(Duration(days: 2));

validator
.ruleFor((event) => event.dateEvent, key: 'dateEvent') //
.exclusiveBetweenOrNull(start: now, end: afterTomorrow);

final event = EventNullableModel()..dateEvent = null;

final result = validator.validate(event);

expect(result.isValid, true);
});
}
15 changes: 15 additions & 0 deletions test/src/validations/greater_than_datetime_validation_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,19 @@ void main() {
expect(result.exceptions.first.message,
"'start' must be greater than date '${now.toString()}'.");
});

test('greater than validation or null ...', () {
final validator = TestLucidValidator<EventNullableModel>();
final now = DateTime.now();

validator
.ruleFor((event) => event.start, key: 'start') //
.greaterThanOrNull(now);

final event = EventNullableModel()..start = null;

final result = validator.validate(event);

expect(result.isValid, true);
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,19 @@ void main() {

expect(result.isValid, true);
});

test('greater than or equal to validation or null ...', () {
final validator = TestLucidValidator<EventNullableModel>();
final now = DateTime.now();

validator
.ruleFor((event) => event.start, key: 'start') //
.greaterThanOrEqualToOrNull(now);

final event = EventNullableModel()..start = null;

final result = validator.validate(event);

expect(result.isValid, true);
});
}
13 changes: 13 additions & 0 deletions test/src/validations/greater_than_validation_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,17 @@ void main() {
expect(result.exceptions.length, 1);
expect(result.exceptions.first.message, "'age' must be greater than '17'.");
});

test('greater than validation or null ...', () {
final validator = TestLucidValidator<UserNullableModel>();
validator
.ruleFor((user) => user.age, key: 'age') //
.greaterThanOrNull(17);

final user = UserNullableModel()..age = null;

final result = validator.validate(user);

expect(result.isValid, true);
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,21 @@ void main() {
expect(result.exceptions.first.message,
"'dateEvent' must be greater than or equal to '${tomorrow.toString()}' date and less than or equal to '${afterTomorrow.toString()}' date.");
});

test('inclusive between validation or null...', () {
final validator = TestLucidValidator<EventNullableModel>();
final now = DateTime.now();
final tomorrow = now.add(Duration(days: 1));
final afterTomorrow = now.add(Duration(days: 2));

validator
.ruleFor((event) => event.dateEvent, key: 'dateEvent') //
.inclusiveBetweenOrNull(start: tomorrow, end: afterTomorrow);

final event = EventNullableModel()..dateEvent = null;

final result = validator.validate(event);

expect(result.isValid, true);
});
}
13 changes: 13 additions & 0 deletions test/src/validations/is_empty_validation_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,17 @@ void main() {

expect(result.exceptions.first.message, "'email' must be empty.");
});

test('is empty validation or null...', () {
final validator = TestLucidValidator<UserNullableModel>();
validator
.ruleFor((user) => user.email, key: 'email') //
.isEmptyOrNull();

final user = UserNullableModel()..email = null;

final result = validator.validate(user);

expect(result.isValid, true);
});
}
14 changes: 14 additions & 0 deletions test/src/validations/is_not_null_validation_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,18 @@ void main() {

expect(error.message, r"'description' must not be null.");
});

test('is not null validation is valid...', () {
final validator = TestLucidValidator<UserModel>();
validator
.ruleFor((e) => e.description, key: 'description') //
.isNotNull()
.maxLength(4);

final user = UserModel()..description = 'desc';

final result = validator.validate(user);

expect(result.isValid, true);
});
}
15 changes: 15 additions & 0 deletions test/src/validations/less_than_datetime_validation_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,19 @@ void main() {
expect(result.exceptions.first.message,
"'end' must be less than date '${now.toString()}'.");
});

test('less than validation ...', () {
final validator = TestLucidValidator<EventNullableModel>();
final now = DateTime.now();

validator
.ruleFor((event) => event.end, key: 'end') //
.lessThanOrNull(now);

final event = EventNullableModel()..end = null;

final result = validator.validate(event);

expect(result.isValid, true);
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,19 @@ void main() {

expect(result.isValid, true);
});

test('less than or equal to validation or null ...', () {
final validator = TestLucidValidator<EventNullableModel>();
final now = DateTime.now();

validator
.ruleFor((event) => event.end, key: 'end') //
.lessThanOrEqualToOrNull(now);

final event = EventNullableModel()..end = null;

final result = validator.validate(event);

expect(result.isValid, true);
});
}
Loading

0 comments on commit afcd27e

Please sign in to comment.