Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In a Flutter widget test, how can I verify a field validation error message?

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.

like image 896
Matt R Avatar asked Oct 16 '19 18:10

Matt R


2 Answers

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:

enter image description here

Hope this answers your question.

like image 136
Darshan Avatar answered Oct 23 '22 01:10

Darshan


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);
like image 43
manusobles Avatar answered Oct 23 '22 01:10

manusobles