Fix and Test Conditional Validator Behavior in FormField (#132714)

In the FormField widget, if a validator is initially set (and validation fails), then subsequently the validator is set to null, the form incorrectly retains its error state. This is not expected behavior as removing the validator should clear any validation errors.
This commit is contained in:
Edgar Jan
2023-09-25 22:17:07 +03:00
committed by GitHub
parent fffbbf279e
commit 79caa8373c
2 changed files with 69 additions and 0 deletions

View File

@@ -524,6 +524,8 @@ class FormFieldState<T> extends State<FormField<T>> with RestorationMixin {
void _validate() {
if (widget.validator != null) {
_errorText.value = widget.validator!(_value);
} else {
_errorText.value = null;
}
}

View File

@@ -945,4 +945,71 @@ void main() {
fieldKey.currentState!.reset();
expect(fieldKey.currentState!.hasInteractedByUser, isFalse);
});
testWidgets('Validator is nullified and error text behaves accordingly',
(WidgetTester tester) async {
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
bool useValidator = false;
late StateSetter setState;
String? validator(String? value) {
if (value == null || value.isEmpty) {
return 'test_error';
}
return null;
}
Widget builder() {
return StatefulBuilder(
builder: (BuildContext context, StateSetter setter) {
setState = setter;
return MaterialApp(
home: MediaQuery(
data: const MediaQueryData(),
child: Directionality(
textDirection: TextDirection.ltr,
child: Center(
child: Material(
child: Form(
key: formKey,
child: TextFormField(
validator: useValidator ? validator : null,
),
),
),
),
),
),
);
},
);
}
await tester.pumpWidget(builder());
// Start with no validator.
await tester.enterText(find.byType(TextFormField), '');
await tester.pump();
formKey.currentState!.validate();
await tester.pump();
expect(find.text('test_error'), findsNothing);
// Now use the validator.
setState(() {
useValidator = true;
});
await tester.pump();
formKey.currentState!.validate();
await tester.pump();
expect(find.text('test_error'), findsOneWidget);
// Remove the validator again and expect the error to disappear.
setState(() {
useValidator = false;
});
await tester.pump();
formKey.currentState!.validate();
await tester.pump();
expect(find.text('test_error'), findsNothing);
});
}