Skip to content

Commit c4dd41d

Browse files
Implement equal length validator
1 parent f6feb9f commit c4dd41d

File tree

2 files changed

+105
-0
lines changed

2 files changed

+105
-0
lines changed

lib/new_api_prototype/collection_validators.dart

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,36 @@ Validator<T> maxLength<T extends Object>(int maxLength,
3434
: null;
3535
};
3636
}
37+
38+
/// Returns a [Validator] function that checks if its input has the length equals
39+
/// to the provided positional parameter `length`. If the input satisfies this
40+
/// condition, the validator returns `null`. Otherwise, it returns the default
41+
/// error message `FormBuilderLocalizations.current.equalLengthErrorText(length)`,
42+
/// if [equalLengthMsg] is not provided.
43+
///
44+
/// # Caveats
45+
/// - Objects that are not collections are considered as collections with
46+
/// length 1.
47+
///
48+
/// # Errors
49+
/// - Throws [AssertionError] if `length` is negative.
50+
/// - Throws [AssertionError] if `allowEmpty` is `false` and `length` is 0.
51+
Validator<T> equalLength<T extends Object>(int length,
52+
{bool allowEmpty = false, String Function(int)? equalLengthMsg}) {
53+
assert(length >= 0, 'The length parameter may not be negative');
54+
assert(!(!allowEmpty && length == 0),
55+
'If empty is not allowed, the target length may not be 0.');
56+
final String errorMsg = equalLengthMsg?.call(length) ??
57+
FormBuilderLocalizations.current.equalLengthErrorText(length);
58+
return (T value) {
59+
// I think it makes more sense to say that scalar objects has length 1 instead of 0.
60+
int valueLength = 1;
61+
62+
if (value is String) valueLength = value.length;
63+
if (value is Iterable) valueLength = value.length;
64+
if (value is Map) valueLength = value.length;
65+
return valueLength == length || (allowEmpty && valueLength == 0)
66+
? null
67+
: errorMsg;
68+
};
69+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
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: equalLength', () {
6+
group('Validations with default error message', () {
7+
test('Should validate the input when it is expected to have length 0',
8+
() {
9+
final Validator<List<int>> v = equalLength(0, allowEmpty: true);
10+
final Validator<Object> v2 = equalLength(0, allowEmpty: true);
11+
12+
expect(v(<int>[]), isNull);
13+
expect(v2(<int>[12]),
14+
FormBuilderLocalizations.current.equalLengthErrorText(0));
15+
expect(
16+
v2(12), FormBuilderLocalizations.current.equalLengthErrorText(0));
17+
});
18+
19+
test(
20+
'Should validate the input when it is expected to have length 1 and does not allow empty',
21+
() {
22+
final Validator<List<int>> v = equalLength(1);
23+
final Validator<Object> v2 = equalLength(1);
24+
25+
expect(v(<int>[0]), isNull);
26+
expect(v2(<String>['0']), isNull);
27+
expect(v2(0), isNull);
28+
expect(v(<int>[]),
29+
FormBuilderLocalizations.current.equalLengthErrorText(1));
30+
expect(v2(<int>[]),
31+
FormBuilderLocalizations.current.equalLengthErrorText(1));
32+
expect(v(<int>[1, 2]),
33+
FormBuilderLocalizations.current.equalLengthErrorText(1));
34+
expect(v2(<Object>[1, '3']),
35+
FormBuilderLocalizations.current.equalLengthErrorText(1));
36+
});
37+
test(
38+
'Should validate the input when it is expected to have length 4 and it allows empty',
39+
() {
40+
final Validator<List<String>> v = equalLength(4, allowEmpty: true);
41+
final Validator<String> v2 = equalLength(4, allowEmpty: true);
42+
43+
expect(v(<String>['1', '2', '3', '4']), isNull);
44+
expect(v(<String>[]), isNull);
45+
expect(v(<String>['2', '3', '4']),
46+
FormBuilderLocalizations.current.equalLengthErrorText(4));
47+
48+
expect(v2('1234'), isNull);
49+
expect(v2(''), isNull);
50+
expect(v2('123'),
51+
FormBuilderLocalizations.current.equalLengthErrorText(4));
52+
});
53+
});
54+
55+
test('Should validate input returning custom message error when invalid',
56+
() {
57+
final customMsg = 'custom msg';
58+
final v = equalLength(3, equalLengthMsg: (_) => customMsg);
59+
60+
expect(v('hey'), isNull);
61+
expect(v([1, '2', 3, 4]), equals(customMsg));
62+
});
63+
test('Should throw AssertionError when length is negative', () {
64+
expect(() => equalLength(-2), throwsAssertionError);
65+
});
66+
test(
67+
'Should throw AssertionError when length is 0 and empty is not allowed',
68+
() {
69+
expect(() => equalLength(0), throwsAssertionError);
70+
});
71+
});
72+
}

0 commit comments

Comments
 (0)