enterText method

Future<void> enterText(
  1. Finder finder,
  2. String text, {
  3. SettlePolicy? settlePolicy,
  4. Duration? visibleTimeout,
  5. Duration? settleTimeout,
  6. Alignment alignment = Alignment.center,
  7. bool enablePatrolLog = true,
  8. bool hideKeyboard = true,
})
inherited

Waits until finder finds at least 1 visible widget and then enters text into it.

Example:

// enters text into the first widget having Key('email')
await $(#email).enterText(user@example.com);

If the finder finds more than 1 widget, you can choose which one to enter text into:

// enters text into the third TextField widget
await $(TextField).at(2).enterText('Code ought to be lean');

This method automatically calls WidgetTester.pumpAndSettle after entering text. If you want to disable this behavior, set settlePolicy to SettlePolicy.noSettle.

See also:

Implementation

Future<void> enterText(
  Finder finder,
  String text, {
  SettlePolicy? settlePolicy,
  Duration? visibleTimeout,
  Duration? settleTimeout,
  Alignment alignment = Alignment.center,
  bool enablePatrolLog = true,
  bool hideKeyboard = true,
}) {
  return TestAsyncUtils.guard(
    () => wrapWithPatrolLog(
      action: 'enterText',
      value: text,
      finder: finder,
      color: AnsiCodes.magenta,
      enablePatrolLog: enablePatrolLog,
      function: () async {
        final resolvedFinder = await waitUntilVisible(
          finder,
          timeout: visibleTimeout,
          alignment: alignment,
          enablePatrolLog: false,
        );

        final editableTextFinder = find.descendant(
          of: resolvedFinder.first,
          matching: find.byType(EditableText),
          matchRoot: true,
        );
        final editableTextState = tester.state<EditableTextState>(
          editableTextFinder,
        );
        final wasFocused = editableTextState.widget.focusNode.hasFocus;
        final usesLiveBinding =
            tester.binding is LiveTestWidgetsFlutterBinding;
        final textEditingValue = TextEditingValue(
          text: text,
          selection: TextSelection.collapsed(offset: text.length),
        );

        if (!kIsWeb && wasFocused) {
          await _enterTextIntoFocusedEditable(
            editableTextState,
            textEditingValue,
          );
        } else {
          if (!kIsWeb) {
            // Fix for enterText() not working in release mode on real iOS devices.
            // See https://github.com/flutter/flutter/pull/89703
            // Also the fix for enterText() is not able to interact with the same
            // textfield 2 times in the same test.
            // See https://github.com/flutter/flutter/issues/134604
            tester.testTextInput.register();
          }

          try {
            // Workaround for enterText() not working in release mode on real iOS devices.
            // [EditableTextState._openInputConnection] is not called when the text field is focused.
            // So we need to attach text input connection manually.
            if (isIOS && kReleaseMode) {
              final effectiveAutofillClient =
                  editableTextState.widget.autofillClient;

              TextInput.attach(
                editableTextState,
                effectiveAutofillClient?.textInputConfiguration ??
                    const TextInputConfiguration(),
              );
            }

            await tester.enterText(resolvedFinder.first, text);
          } finally {
            if (!kIsWeb) {
              tester.testTextInput.closeConnection();
              await tester.pump();
              tester.binding.focusedEditable = null;

              tester.testTextInput.reset();
              tester.testTextInput.unregister();
            }
          }
        }

        if (!kIsWeb && editableTextState.mounted) {
          if (hideKeyboard) {
            editableTextState.widget.focusNode.unfocus();
            await tester.pump();
          } else if (usesLiveBinding) {
            editableTextState.requestKeyboard();
            await tester.pump();
          }
        }
        await _performPump(
          settlePolicy: settlePolicy,
          settleTimeout: settleTimeout,
        );
      },
    ),
  );
}