Skip to content

Commit 723f1ed

Browse files
authored
Merge pull request #529 from awhitford/test-fields-1
Few bug fixes, but mostly added unit testing for fields.
2 parents 013729c + fce34f3 commit 723f1ed

18 files changed

+573
-232
lines changed

lib/src/fields/form_builder_choice_chips.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ class FormBuilderChoiceChip<T> extends FormBuilderField<T> {
309309
children: <Widget>[
310310
for (FormBuilderFieldOption<T> option in options)
311311
ChoiceChip(
312-
label: option.child,
312+
label: option,
313313
selected: field.value == option.value,
314314
onSelected: state.readOnly
315315
? null

lib/src/fields/form_builder_dropdown.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ class FormBuilderDropdown<T> extends FormBuilderField<T> {
211211
this.autofocus = false,
212212
this.dropdownColor,
213213
this.focusColor,
214-
this.itemHeight,
214+
this.itemHeight = kMinInteractiveDimension,
215215
this.selectedItemBuilder,
216216
}) : /*: assert(allowClear == true || clearIcon != null)*/ super(
217217
key: key,
@@ -244,7 +244,7 @@ class FormBuilderDropdown<T> extends FormBuilderField<T> {
244244
children: <Widget>[
245245
Expanded(
246246
child: DropdownButtonHideUnderline(
247-
child: DropdownButton(
247+
child: DropdownButton<T>(
248248
isExpanded: isExpanded,
249249
hint: hint,
250250
items: items,
@@ -266,7 +266,7 @@ class FormBuilderDropdown<T> extends FormBuilderField<T> {
266266
iconEnabledColor: iconEnabledColor,
267267
onChanged: (state.readOnly || !enabled)
268268
? null
269-
: (T value) => _changeValue<T>(field, value),
269+
: (value) => _changeValue<T>(field, value),
270270
onTap: onTap,
271271
focusNode: state.effectiveFocusNode,
272272
autofocus: autofocus,

lib/src/fields/form_builder_filter_chips.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ class FormBuilderFilterChip<T> extends FormBuilderField<List<T>> {
107107
children: <Widget>[
108108
for (FormBuilderFieldOption<T> option in options)
109109
FilterChip(
110-
label: option.child,
110+
label: option,
111111
selected: field.value.contains(option.value),
112112
onSelected: (state.readOnly ||
113113
(maxChips != null &&

lib/src/fields/form_builder_touch_spin.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ class FormBuilderTouchSpin extends FormBuilderField<double> {
5757
AutovalidateMode autovalidateMode = AutovalidateMode.disabled,
5858
VoidCallback onReset,
5959
FocusNode focusNode,
60-
this.step,
61-
this.min = 1,
62-
this.max = 9999,
60+
this.step = 1.0,
61+
this.min = 1.0,
62+
this.max = 9999999.0,
6363
this.iconSize = 24.0,
6464
this.displayFormat,
6565
this.subtractIcon = const Icon(Icons.remove),

lib/src/form_builder_validators.dart

Lines changed: 58 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ class FormBuilderValidators {
6363
}) {
6464
return (valueCandidate) {
6565
if (valueCandidate != null) {
66+
assert(valueCandidate is num || valueCandidate is String);
6667
final number = valueCandidate is num
6768
? valueCandidate
6869
: num.tryParse(valueCandidate.toString());
@@ -87,6 +88,7 @@ class FormBuilderValidators {
8788
}) {
8889
return (valueCandidate) {
8990
if (valueCandidate != null) {
91+
assert(valueCandidate is num || valueCandidate is String);
9092
final number = valueCandidate is num
9193
? valueCandidate
9294
: num.tryParse(valueCandidate.toString());
@@ -108,7 +110,9 @@ class FormBuilderValidators {
108110
bool allowEmpty = false,
109111
String errorText,
110112
}) {
113+
assert(minLength > 0);
111114
return (valueCandidate) {
115+
assert(null == valueCandidate || valueCandidate is String);
112116
final valueLength = valueCandidate?.length ?? 0;
113117
if (valueLength < minLength && (!allowEmpty || valueLength > 0)) {
114118
return errorText ??
@@ -125,10 +129,15 @@ class FormBuilderValidators {
125129
num maxLength, {
126130
String errorText,
127131
}) {
132+
assert(maxLength > 0);
128133
return (valueCandidate) {
129-
if (valueCandidate != null && valueCandidate.length > maxLength) {
130-
return errorText ??
131-
FormBuilderLocalizations.of(context).maxLengthErrorText(maxLength);
134+
if (null != valueCandidate) {
135+
assert(valueCandidate is String);
136+
if (valueCandidate.length > maxLength) {
137+
return errorText ??
138+
FormBuilderLocalizations.of(context)
139+
.maxLengthErrorText(maxLength);
140+
}
132141
}
133142
return null;
134143
};
@@ -140,8 +149,9 @@ class FormBuilderValidators {
140149
String errorText,
141150
}) {
142151
return (valueCandidate) {
143-
if (valueCandidate != null && valueCandidate.isNotEmpty) {
144-
if (!isEmail(valueCandidate.trim())) {
152+
if (null != valueCandidate) {
153+
assert(valueCandidate is String);
154+
if (valueCandidate.isNotEmpty && !isEmail(valueCandidate.trim())) {
145155
return errorText ??
146156
FormBuilderLocalizations.of(context).emailErrorText;
147157
}
@@ -162,14 +172,16 @@ class FormBuilderValidators {
162172
List<String> hostBlacklist = const [],
163173
}) {
164174
return (valueCandidate) {
165-
if (valueCandidate != null && valueCandidate.isNotEmpty) {
166-
if (!isURL(valueCandidate,
167-
protocols: protocols,
168-
requireTld: requireTld,
169-
requireProtocol: requireProtocol,
170-
allowUnderscore: allowUnderscore,
171-
hostWhitelist: hostWhitelist,
172-
hostBlacklist: hostBlacklist)) {
175+
if (null != valueCandidate) {
176+
assert(valueCandidate is String);
177+
if (valueCandidate.isNotEmpty &&
178+
!isURL(valueCandidate,
179+
protocols: protocols,
180+
requireTld: requireTld,
181+
requireProtocol: requireProtocol,
182+
allowUnderscore: allowUnderscore,
183+
hostWhitelist: hostWhitelist,
184+
hostBlacklist: hostBlacklist)) {
173185
return errorText ?? FormBuilderLocalizations.of(context).urlErrorText;
174186
}
175187
}
@@ -184,8 +196,10 @@ class FormBuilderValidators {
184196
String errorText,
185197
}) {
186198
return (valueCandidate) {
187-
if (valueCandidate != null && valueCandidate.isNotEmpty) {
188-
if (!RegExp(pattern).hasMatch(valueCandidate)) {
199+
if (null != valueCandidate) {
200+
assert(valueCandidate is String);
201+
if (valueCandidate.isNotEmpty &&
202+
!RegExp(pattern).hasMatch(valueCandidate)) {
189203
return errorText ??
190204
FormBuilderLocalizations.of(context).matchErrorText;
191205
}
@@ -200,9 +214,12 @@ class FormBuilderValidators {
200214
String errorText,
201215
}) {
202216
return (valueCandidate) {
203-
if (valueCandidate.isNotEmpty && num.tryParse(valueCandidate) == null) {
204-
return errorText ??
205-
FormBuilderLocalizations.of(context).numericErrorText;
217+
if (null != valueCandidate) {
218+
assert(valueCandidate is String);
219+
if (valueCandidate.isNotEmpty && num.tryParse(valueCandidate) == null) {
220+
return errorText ??
221+
FormBuilderLocalizations.of(context).numericErrorText;
222+
}
206223
}
207224
return null;
208225
};
@@ -215,10 +232,13 @@ class FormBuilderValidators {
215232
int radix,
216233
}) {
217234
return (valueCandidate) {
218-
if (valueCandidate.isNotEmpty &&
219-
int.tryParse(valueCandidate, radix: radix) == null) {
220-
return errorText ??
221-
FormBuilderLocalizations.of(context).numericErrorText;
235+
if (null != valueCandidate) {
236+
assert(valueCandidate is String);
237+
if (valueCandidate.isNotEmpty &&
238+
int.tryParse(valueCandidate, radix: radix) == null) {
239+
return errorText ??
240+
FormBuilderLocalizations.of(context).numericErrorText;
241+
}
222242
}
223243
return null;
224244
};
@@ -231,10 +251,13 @@ class FormBuilderValidators {
231251
String errorText,
232252
}) {
233253
return (valueCandidate) {
234-
if (valueCandidate.isNotEmpty &&
235-
double.tryParse(valueCandidate) == null) {
236-
return errorText ??
237-
FormBuilderLocalizations.of(context).numericErrorText;
254+
if (null != valueCandidate) {
255+
assert(valueCandidate is String);
256+
if (valueCandidate.isNotEmpty &&
257+
double.tryParse(valueCandidate) == null) {
258+
return errorText ??
259+
FormBuilderLocalizations.of(context).numericErrorText;
260+
}
238261
}
239262
return null;
240263
};
@@ -246,8 +269,9 @@ class FormBuilderValidators {
246269
String errorText,
247270
}) {
248271
return (valueCandidate) {
249-
if (valueCandidate != null && valueCandidate.isNotEmpty) {
250-
if (!isCreditCard(valueCandidate)) {
272+
if (null != valueCandidate) {
273+
assert(valueCandidate is String);
274+
if (valueCandidate.isNotEmpty && !isCreditCard(valueCandidate)) {
251275
return errorText ??
252276
FormBuilderLocalizations.of(context).creditCardErrorText;
253277
}
@@ -265,8 +289,9 @@ class FormBuilderValidators {
265289
String errorText,
266290
}) {
267291
return (valueCandidate) {
268-
if (valueCandidate != null && valueCandidate.isNotEmpty) {
269-
if (!isIP(valueCandidate, version)) {
292+
if (null != valueCandidate) {
293+
assert(valueCandidate is String);
294+
if (valueCandidate.isNotEmpty && !isIP(valueCandidate, version)) {
270295
return errorText ?? FormBuilderLocalizations.of(context).ipErrorText;
271296
}
272297
}
@@ -280,8 +305,9 @@ class FormBuilderValidators {
280305
String errorText,
281306
}) {
282307
return (valueCandidate) {
283-
if (valueCandidate != null && valueCandidate.isNotEmpty) {
284-
if (!isDate(valueCandidate)) {
308+
if (null != valueCandidate) {
309+
assert(valueCandidate is String);
310+
if (valueCandidate.isNotEmpty && !isDate(valueCandidate)) {
285311
return errorText ??
286312
FormBuilderLocalizations.of(context).dateStringErrorText;
287313
}

lib/src/widgets/grouped_checkbox.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ class GroupedCheckbox<T> extends StatefulWidget {
181181
final ControlAffinity controlAffinity;
182182

183183
GroupedCheckbox({
184+
Key key,
184185
@required this.options,
185186
@required this.orientation,
186187
@required this.onChanged,
@@ -202,7 +203,7 @@ class GroupedCheckbox<T> extends StatefulWidget {
202203
this.wrapVerticalDirection = VerticalDirection.down,
203204
this.separator,
204205
this.controlAffinity = ControlAffinity.leading,
205-
});
206+
}) : super(key: key);
206207

207208
@override
208209
_GroupedCheckboxState<T> createState() => _GroupedCheckboxState<T>();
@@ -276,7 +277,7 @@ class _GroupedCheckboxState<T> extends State<GroupedCheckbox<T>> {
276277
tristate: widget.tristate,
277278
onChanged: isOptionDisabled
278279
? null
279-
: (bool selected) {
280+
: (selected) {
280281
selected
281282
? selectedListItems.add(optionValue)
282283
: selectedListItems.remove(optionValue);
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_test/flutter_test.dart';
3+
import 'package:flutter_form_builder/flutter_form_builder.dart';
4+
import 'form_builder_tester.dart';
5+
6+
void main() {
7+
testWidgets('FormBuilderCheckboxGroup -- 1,3', (WidgetTester tester) async {
8+
const widgetName = 'cbg1';
9+
final testWidget = FormBuilderCheckboxGroup<int>(
10+
name: widgetName,
11+
options: const [
12+
FormBuilderFieldOption(key: ValueKey('1'), value: 1),
13+
FormBuilderFieldOption(key: ValueKey('2'), value: 2),
14+
FormBuilderFieldOption(key: ValueKey('3'), value: 3),
15+
],
16+
);
17+
await tester.pumpWidget(buildTestableFieldWidget(testWidget));
18+
19+
expect(formSave(), isTrue);
20+
expect(formValue(widgetName), isNull);
21+
await tester.tap(find.byKey(ValueKey('1')));
22+
await tester.pumpAndSettle();
23+
expect(formSave(), isTrue);
24+
expect(formValue(widgetName), equals(const [1]));
25+
await tester.tap(find.byKey(ValueKey('3')));
26+
await tester.pumpAndSettle();
27+
expect(formSave(), isTrue);
28+
expect(formValue(widgetName), equals(const [1, 3]));
29+
});
30+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_test/flutter_test.dart';
3+
import 'package:flutter_form_builder/flutter_form_builder.dart';
4+
import 'form_builder_tester.dart';
5+
6+
void main() {
7+
testWidgets('FormBuilderCheckbox -- Off/On/Off', (WidgetTester tester) async {
8+
const checkboxName = 'cb1';
9+
final testWidget = FormBuilderCheckbox(
10+
name: checkboxName,
11+
title: const Text('Checkbox 1'),
12+
initialValue: false,
13+
);
14+
final widgetFinder = find.byWidget(testWidget);
15+
16+
await tester.pumpWidget(buildTestableFieldWidget(testWidget));
17+
18+
expect(formSave(), isTrue);
19+
expect(formValue(checkboxName), isFalse);
20+
await tester.tap(widgetFinder);
21+
await tester.pumpAndSettle();
22+
expect(formSave(), isTrue);
23+
expect(formValue(checkboxName), isTrue);
24+
await tester.tap(widgetFinder);
25+
await tester.pumpAndSettle();
26+
expect(formSave(), isTrue);
27+
expect(formValue(checkboxName), isFalse);
28+
});
29+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_test/flutter_test.dart';
3+
import 'package:flutter_form_builder/flutter_form_builder.dart';
4+
import 'form_builder_tester.dart';
5+
6+
void main() {
7+
testWidgets('FormBuilderChoiceChip -- 1,3', (WidgetTester tester) async {
8+
const widgetName = 'cc1';
9+
final testWidget = FormBuilderChoiceChip<int>(
10+
name: widgetName,
11+
options: const [
12+
FormBuilderFieldOption(key: ValueKey('1'), value: 1),
13+
FormBuilderFieldOption(key: ValueKey('2'), value: 2),
14+
FormBuilderFieldOption(key: ValueKey('3'), value: 3),
15+
],
16+
);
17+
await tester.pumpWidget(buildTestableFieldWidget(testWidget));
18+
19+
expect(formSave(), isTrue);
20+
expect(formValue(widgetName), isNull);
21+
await tester.tap(find.byKey(ValueKey('1')));
22+
await tester.pumpAndSettle();
23+
expect(formSave(), isTrue);
24+
expect(formValue(widgetName), equals(1));
25+
await tester.tap(find.byKey(ValueKey('3')));
26+
await tester.pumpAndSettle();
27+
expect(formSave(), isTrue);
28+
expect(formValue(widgetName), equals(3));
29+
});
30+
}

0 commit comments

Comments
 (0)