emitsThrough function

StreamMatcher emitsThrough (dynamic matcher)

Returns a StreamMatcher that matches any number of events followed by events that match matcher.

This consumes all events matched by matcher, as well as all events before. If the stream emits a done event without matching matcher, this fails and consumes no events.

Implementation

StreamMatcher emitsThrough(matcher) {
  var streamMatcher = emits(matcher);
  return StreamMatcher((queue) async {
    var failures = <String>[];

    tryHere() => queue.withTransaction((copy) async {
          var result = await streamMatcher.matchQueue(copy);
          if (result == null) return true;
          failures.add(result);
          return false;
        });

    while (await queue.hasNext) {
      if (await tryHere()) return null;
      await queue.next;
    }

    // Try after the queue is done in case the matcher can match an empty
    // stream.
    if (await tryHere()) return null;

    var result = "never did ${streamMatcher.description}";

    var failureMessages =
        bullet(failures.where((failure) => failure.isNotEmpty));
    if (failureMessages.isNotEmpty) {
      result += result.contains("\n") ? "\n" : " ";
      result += "because it:\n$failureMessages";
    }

    return result;
  }, "eventually ${streamMatcher.description}");
}