Skip to content

Commit 926b96f

Browse files
Implement between length validator
1 parent 0f63d93 commit 926b96f

File tree

5 files changed

+115
-2
lines changed

5 files changed

+115
-2
lines changed

lib/new_api_prototype/collection_validators.dart

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,50 @@ Validator<T> maxLength<T extends Object>(int maxLength,
6161
};
6262
}
6363

64+
/// Temporary error message for `betweenLength` validator.
65+
String betweenLengthTemporaryErrorMessage(
66+
{required int min, required int max}) =>
67+
'Value must have a length that is between $min and $max, inclusive';
68+
69+
/// Returns a [Validator] function that checks if its input has a length that is
70+
/// between `minLength` and `maxLength`, inclusive. If the input satisfies this
71+
/// condition, the validator returns `null`. Otherwise, it returns the default
72+
/// error message
73+
/// `FormBuilderLocalizations.current.betweenLengthErrorText(minLength, maxLength)`,
74+
/// if [betweenLengthMsg] is not provided.
75+
///
76+
/// # Caveats
77+
/// - Objects that are not collections are considered as collections with
78+
/// length 1.
79+
///
80+
/// # Errors
81+
/// - Throws [AssertionError] if `minLength` or `maxLength` are negative.
82+
/// - Throws [AssertionError] if `maxLength` is less than `minLength`.
83+
Validator<T> betweenLength<T extends Object>(
84+
int minLength,
85+
int maxLength, {
86+
String Function({required int min, required int max})? betweenLengthMsg,
87+
}) {
88+
assert(minLength >= 0, 'The "minLength" parameter may not be negative');
89+
assert(maxLength >= minLength,
90+
'The "maxLength" parameter must be greater than or equal to "minLength"');
91+
return (T value) {
92+
// I think it makes more sense to say that scalar objects has length 1 instead of 0.
93+
int valueLength = 1;
94+
95+
if (value is String) valueLength = value.length;
96+
if (value is Iterable) valueLength = value.length;
97+
if (value is Map) valueLength = value.length;
98+
99+
return (valueLength < minLength || valueLength > maxLength)
100+
? betweenLengthMsg?.call(min: minLength, max: maxLength) ??
101+
// TODO (ArturAssisComp): add the translated version of this message
102+
// FormBuilderLocalizations.current.betweenLengthErrorText(maxLength)
103+
betweenLengthTemporaryErrorMessage(min: minLength, max: maxLength)
104+
: null;
105+
};
106+
}
107+
64108
/// Returns a [Validator] function that checks if its input has the length equals
65109
/// to the provided positional parameter `length`. If the input satisfies this
66110
/// condition, the validator returns `null`. Otherwise, it returns the default

lib/new_api_prototype/generic_type_validators.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ Validator<T> isEqual<T extends Object?>(T value,
6060
/// ```
6161
Validator<T> isTrue<T extends Object>(
6262
{String? isTrueMsg, bool caseSensitive = false, bool trim = true}) {
63-
return (value) {
63+
return (T value) {
6464
final (isValid, typeTransformedValue) = _isBoolValidateAndConvert(
6565
value,
6666
caseSensitive: caseSensitive,
@@ -100,7 +100,7 @@ Validator<T> isTrue<T extends Object>(
100100
/// ```
101101
Validator<T> isFalse<T extends Object>(
102102
{String? isFalseMsg, bool caseSensitive = false, bool trim = true}) {
103-
return (value) {
103+
return (T value) {
104104
final (isValid, typeTransformedValue) = _isBoolValidateAndConvert(
105105
value,
106106
caseSensitive: caseSensitive,
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import 'package:flutter_test/flutter_test.dart';
2+
import 'package:form_builder_validators/form_builder_validators.dart';
3+
4+
void main() {
5+
group('Validator: betweenLength', () {
6+
group('Validators with default error message', () {
7+
test(
8+
'Should validate the input when it is expected to have minLength equals to maxLength',
9+
() {
10+
final Validator<List<int>> v = betweenLength(0, 0);
11+
final Validator<Object> v2 = betweenLength(3, 3);
12+
13+
expect(v(<int>[]), isNull);
14+
expect(
15+
v(<int>[12]), betweenLengthTemporaryErrorMessage(min: 0, max: 0));
16+
expect(v2(<int>[12, 23, 456]), isNull);
17+
expect(v2(12), betweenLengthTemporaryErrorMessage(min: 3, max: 3));
18+
});
19+
test(
20+
'Should validate the input when it is expected to have minLength 1 and maxLength 5',
21+
() {
22+
final Validator<List<int>> v = betweenLength(1, 5);
23+
final Validator<Object> v2 = betweenLength(1, 5);
24+
25+
expect(v(<int>[]), betweenLengthTemporaryErrorMessage(min: 1, max: 5));
26+
expect(v(<int>[0]), isNull);
27+
expect(v(<int>[0, 1]), isNull);
28+
expect(v(<int>[0, 2, 3]), isNull);
29+
expect(v(<int>[23, 432, 52, 65, 1]), isNull);
30+
expect(v(<int>[1, 2, 3, 4, 5, 6]),
31+
betweenLengthTemporaryErrorMessage(min: 1, max: 5));
32+
expect(v(<int>[1, 2, 3, 4, 5, 6, 7]),
33+
betweenLengthTemporaryErrorMessage(min: 1, max: 5));
34+
35+
expect(v2(<int>[]), betweenLengthTemporaryErrorMessage(min: 1, max: 5));
36+
expect(v2(''), betweenLengthTemporaryErrorMessage(min: 1, max: 5));
37+
expect(v2(<String>['0']), isNull);
38+
expect(v2(0), isNull);
39+
expect(v2(<Object>[1, '3']), isNull);
40+
expect(v2('hi '), isNull);
41+
expect(
42+
v2(' '), betweenLengthTemporaryErrorMessage(min: 1, max: 5));
43+
});
44+
});
45+
46+
test('Should validate input returning custom message error when invalid',
47+
() {
48+
const String customMsg = 'custom msg';
49+
final Validator<Object> v = betweenLength(3, 4,
50+
betweenLengthMsg: ({required int min, required int max}) =>
51+
customMsg);
52+
53+
expect(v(89), equals(customMsg));
54+
expect(v(<Object>[1, '2', 3, 4]), isNull);
55+
expect(v(' '), isNull);
56+
});
57+
group('Throws assertion error', () {
58+
test('Should throw AssertionError when minLength is negative', () {
59+
expect(() => betweenLength(-2, 3), throwsAssertionError);
60+
expect(() => betweenLength(-2, -3), throwsAssertionError);
61+
});
62+
test('Should throw AssertionError when maxLength is less than minLength',
63+
() {
64+
expect(() => betweenLength(3, 2), throwsAssertionError);
65+
expect(() => betweenLength(3, -2), throwsAssertionError);
66+
});
67+
});
68+
});
69+
}

test/new_api_testing/string_validators/is_false_validator_test.dart renamed to test/new_api_testing/generic_type_validators/is_false_validator_test.dart

File renamed without changes.

test/new_api_testing/string_validators/is_true_validator_test.dart renamed to test/new_api_testing/generic_type_validators/is_true_validator_test.dart

File renamed without changes.

0 commit comments

Comments
 (0)