waitFor method

  1. @protected
Future<Finder> waitFor(
  1. dynamic testableId, {
  2. required CancelToken cancelToken,
  3. required TestController tester,
  4. Duration? timeout,
})

Waits for a widget with a key that has testableId as the value.

Implementation

@protected
Future<test.Finder> waitFor(
  dynamic testableId, {
  required CancelToken cancelToken,
  required TestController tester,
  Duration? timeout,
}) async {
  timeout ??= tester.delays.defaultTimeout;

  var controller = StreamController<void>.broadcast();
  var name = "waitFor('$testableId')";
  try {
    var waiter = () async {
      var end =
          DateTime.now().millisecondsSinceEpoch + timeout!.inMilliseconds;
      test.Finder? finder;
      var found = false;
      while (found != true && DateTime.now().millisecondsSinceEpoch < end) {
        try {
          finder = test.find.byKey(ValueKey<String?>(testableId));
          finder.evaluate().first;
          found = true;
        } catch (e) {
          if (cancelToken.cancelled == true) {
            throw Exception('[CANCELLED]: step was cancelled by the test');
          }

          await Future.delayed(Duration(milliseconds: 100));
        }
      }

      if (found != true) {
        throw Exception('testableId: [$testableId] -- Timeout exceeded.');
      }
      return finder!;
    };

    var sleeper = sleep(
      timeout,
      cancelStream: controller.stream,
      error: true,
      message: '[$name]: ${timeout.inSeconds} seconds',
      tester: tester,
    );

    var result = await waiter();
    if (cancelToken.cancelled == true) {
      throw Exception('[CANCELLED]: step was cancelled by the test');
    }

    controller.add(null);
    await sleeper;
    if (cancelToken.cancelled == true) {
      throw Exception('[CANCELLED]: step was cancelled by the test');
    }

    try {
      var finder = result.evaluate().first;
      if (finder.widget is Testable) {
        var element = finder as StatefulElement;
        var state = element.state;
        if (state is TestableState) {
          _console('flash: [$testableId]', Level.FINEST);
          await state.flash();
          _console('flash complete: [$testableId]', Level.FINEST);
        }
      }
    } catch (e) {
      // no-op
    }

    return result;
  } catch (e) {
    log(
      'ERROR: [$name] -- $e',
      tester: tester,
    );
    rethrow;
  } finally {
    await controller.close();
  }
}