I'm writing a widget test for a Flutter form, and want to verify that after form submission, validation fails, and errorText
for one of the fields is displayed and is as expected.
The code for the field looks like:
Form(key: _formKey, ...
TextFormField(validator: validateEmail, ...)
For the test assertion, I've tried things like
expect(find.text('Please fill in your email.'), findsOneWidget);
With no success. Hoping someone can point me in the right direction.
I recreated your case and was able to validate the inline error message. The idea is to add a delay of 1 second before we could test assertion. Here's what I did:
main.dart
code to display textformfield
and validate Email upon tapping Send
button:
TextFormField(
decoration: new InputDecoration(hintText: 'Email ID'),
keyboardType: TextInputType.emailAddress,
maxLength: 32,
validator: validateEmail,
onSaved: (String val) {
email = val;
}),
validateEmail
method snippet:
if (value.length == 0) {
return "Email is Required";
} else if(!regExp.hasMatch(value)){
return "Invalid Email";
}else {
return null;
}
Widget test to validate the inline error message for email field:
void main() {
testWidgets('validate email inline error message',
(WidgetTester tester) async {
await tester.pumpWidget(MyApp());
final buttonFinder = find.text('Send');
final emailErrorFinder = find.text('Email is Required');
await tester.tap(buttonFinder);
print('button tapped');
await tester.pump(const Duration(milliseconds: 100)); // add delay
expect(emailErrorFinder, findsOneWidget);
print('validated email inline error');
});
}
Test result:
Hope this answers your question.
If you want to verify the validation error message from a TextFormField
, it is not straightforward but possible.
We can use the key of our TextFormField
:
TextFormField(
key: const Key('field_key'),
// Rest of attributes...
),
Then we scope our find.text()
to find only within the descendants of the TextFormField
like this:
final textFormField = find.byKey(const Key('field_key'));
final textFinder = find.text('Email is required');
final validationMessage = find.descendant(of: textFormField, matching: textFinder)
.first.evaluate().single.widget as Text;
expect(validationMessage.data, 'Email is required');
Alternatively, we can be a little bit less strict by just checking that the text exists as a child of the TextFormField
:
final textFormField = find.byKey(const Key('field_key'));
final textFinder = find.text('Email is required');
final validationMessageFinder = find.descendant(of: textFormField, matching: textFinder);
expect(validationMessageFinder, findsOneWidget);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With