Тесты виджета Flutter не могут найти InputDecoration.errorText

Примечание: это для веб-приложения Flutter.

Я тестирую TextField, чтобы показать, что если ввод недействителен, отображается текст ошибки, указанный в InputDecoration.

Виджет работает надлежащим образом, когда я запускаю все приложение и взаимодействую с ним вручную.

Вот определение моего TextField:

TextField(
  key: ValueKey('IntSpinner-TEXT'),
  controller: _controller,
  keyboardType: _keyboardType(),
  inputFormatters: widget.inputFormatters ?? [formatter],
  decoration: InputDecoration(
    border: const OutlineInputBorder(),
    errorText: _validInput ? null : 'Invalid input',
  ),
);

У меня есть слушатель на контроллере TextField, который проверяет новое значение и устанавливает для _validInput значение true или false соответственно.

А вот код моего теста:

    testWidgets('should flag invalid values', (WidgetTester tester) async {
      int x;
      await tester.pumpWidget(MaterialApp(
        home: Card(
          child: Column(
            children: [
              IntSpinner( // this widget contains my TextField
                key: ValueKey('IntSpinner'),
                onChanged: (value) => x = value,
              ),
            ],
          ),
        ),
      ));

      // Enter valid text
      await tester.enterText(find.byKey(ValueKey('IntSpinner-TEXT')), '-2200');
      expect(x, equals(-2200));

      // Enter invalid text
      await tester.enterText(find.byKey(ValueKey('IntSpinner-TEXT')), '2-200');
      expect(x, equals(-2200)); // unchanged!!
      
      TextField txt = tester.widget(find.byKey(ValueKey('IntSpinner-TEXT')));
      expect(txt.decoration.errorText, equals('Invalid input'));
    });

Я получаю такую ​​ошибку:

══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure object was thrown running a test:
  Expected: 'Invalid input'
  Actual: <null>
   Which: not an <Instance of 'String'>

Я вижу то же самое в отладчике - inputDecoration.errorText имеет значение null. Но когда я запускаю приложение в браузере, я ясно вижу (используя Flutter Widget Inspector), что errorText установлен должным образом (я также вижу, что TextField закрашивается с помощью errorText).

Фрагмент вывода Widget Inspector:

введите описание изображения здесь

Как правильно проверить TextField.decoration.errorText из теста виджета Flutter?


person beer geek    schedule 21.10.2020    source источник
comment
Правильно ли ваш слушатель устанавливает _validInput для начального значения controller.text (т.е. когда вы не указываете начальное значение и ничего не вводите)?   -  person Joy Terence    schedule 21.10.2020
comment
да. На самом деле я даю действительное начальное значение. Более того, я могу визуально проверить работающее приложение, и все кажется правильным, насколько виден errorText или нет.   -  person beer geek    schedule 21.10.2020
comment
Можете ли вы сделать этот тест своим первым? Я подозреваю, что причиной этого являются выполненные выше задания.   -  person Joy Terence    schedule 22.10.2020
comment
Готово, и без разницы. По-прежнему возвращает null для errorText.   -  person beer geek    schedule 22.10.2020
comment
Проблема со значением _validInput; Я добавил печать ('build: $ _ validInput'); в верхней части моего метода Widget.build (), и он всегда выводит build: true.   -  person beer geek    schedule 22.10.2020
comment
Сделав еще немного протоколирования, я вижу, что устанавливаю _validInput внутри закрытия setState (), но после этого изменения метод сборки никогда не вызывается.   -  person beer geek    schedule 22.10.2020


Ответы (1)


У меня есть работающее решение. Я бы хотел, чтобы кто-нибудь знающий это подтвердил.

Перестройка виджета не запускается, если _validInput установлен во время записи теста. Вместо этого кажется, что я дождусь завершения редактирования. Я подделываю это, перемещая фокус с TextField на другое TextField (используя WidgetTester.showKeyboard (finder)).

Итак, теперь мои тестовые шаги следующие:

      // print('Enter valid text');
      await tester.enterText(find.byKey(ValueKey('IntSpinner-TEXT')), '-2200');
      expect(x, equals(-2200));
      
      // move the focus somewhere else ... anywhere else
      await tester.showKeyboard(find.byKey(Key('FOO')));
      TextField txt = tester.widget(find.byKey(ValueKey('IntSpinner-TEXT')));
      expect(txt.decoration.errorText, isNull);

      // print('Enter invalid text');
      await tester.enterText(find.byKey(ValueKey('IntSpinner-TEXT')), '2-200');
      expect(x, equals(-2200)); // unchanged!!

      // move the focus somewhere else ... anywhere else
      await tester.showKeyboard(find.byKey(Key('FOO')));
      txt = tester.widget(find.byKey(ValueKey('IntSpinner-TEXT')));
      expect(txt.decoration.errorText, equals('Invalid input'));

Это заставляет мой тест работать; вопрос в том, почему errorText отображается в запущенном приложении без перемещения фокуса на другой виджет?

person beer geek    schedule 22.10.2020