How to unit Test a Flutter TextFormField maxlines

5,380

Solution 1

I don't know if this is a good solution but as i set the value of my TextFormField i can find the EditableText widget directly. of this widget i can find test the property maxLines.

final EditableText formfield =
   tester.widget<EditableText>(find.text('testvalue'));

expect(formfield.maxLines, 2);

Solution 2

The reason you can't see properties such as maxLines or maxLength is because they belong to the TextField class.

Take a look at the documentation of the TextFormField constructor in the source file:

  /// Creates a [FormField] that contains a [TextField].
  ///
  /// When a [controller] is specified, [initialValue] must be null (the
  /// default). If [controller] is null, then a [TextEditingController]
  /// will be constructed automatically and its `text` will be initialized
  /// to [initialValue] or the empty string.
  ///
  /// For documentation about the various parameters, see the [TextField] class
  /// and [new TextField], the constructor.

Unfortunately you can't retrieve the TextField object from a TextFormField, you'll have to find the TextField object through a finder instead.

Let's assume you have a form with 2 fields - first name and last name. What you need to do is find all widgets of type TextField, add them to a list and then you can loop through each element of the list and run your test. Here's an example:

  testWidgets('Form fields have the correct maximum length and number of lines',
      (WidgetTester tester) async {
    await tester.pumpWidget(MaterialApp(
      home: Scaffold(
        body: Form(
          child: Column(
            children: <Widget>[
              TextFormField(
                key: Key('first_name'),
                decoration: InputDecoration(hintText: 'First name'),
                maxLines: 1,
                maxLength: 50,
                obscureText: true,
              ),
              TextFormField(
                key: Key('last_name'),
                decoration: InputDecoration(hintText: 'Last name'),
                maxLines: 1,
                maxLength: 25,
              ),
            ],
          ),
        ),
      ),
    ));

    List<TextField> formFields = List<TextField>();

    find.byType(TextField).evaluate().toList().forEach((element) {
      formFields.add(element.widget);
    });

    formFields.forEach((element) {
      expect(element.maxLines, 1);

      switch (element.decoration.hintText) {
        case 'First name':
          expect(element.maxLength, 50);
          break;

        case 'Last name':
          expect(element.maxLength, 25);
          break;
      }
    });
  });

If you only one field, you could do this instead:

TextField textField = find.byType(TextField).evaluate().first.widget as TextField;

expect(textField.maxLines, 1);
expect(textField.maxLength, 50);
Share:
5,380
autlunatic
Author by

autlunatic

Updated on December 11, 2022

Comments

  • autlunatic
    autlunatic over 1 year

    Is it possible to write a unit test that verifies that the maxLines property of a TextFormField is set correctly. I can not find a way to access the property:

    i create a TextFormField

    final field = TextFormField(
        initialValue: "hello",
        key: Key('textformfield'),
        maxLines: 2,
      );
    

    then in the test i get access to the form field with tester.widget

     final formfield =
        await tester.widget<TextFormField>(find.byKey(Key('textformfield')));
    

    but since the maxLines property is passed to the Builder which returns a Textfield, how can i get access to the textfield.

    Or is there an completely other ways to verify this?