emitsThrough function

StreamMatcher emitsThrough(
  1. Object? 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(Object? matcher) {
  var streamMatcher = emits(matcher);
  return StreamMatcher((queue) async {
    var failures = <String>[];

    Future<bool> 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}');
}