| // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| import 'dart:async'; |
| |
| import 'package:async/async.dart'; |
| import 'package:term_glyph/term_glyph.dart' as glyph; |
| import 'package:test/test.dart'; |
| |
| import '../utils.dart'; |
| |
| void main() { |
| setUpAll(() { |
| glyph.ascii = true; |
| }); |
| |
| Stream stream; |
| StreamQueue queue; |
| Stream errorStream; |
| StreamQueue errorQueue; |
| setUp(() { |
| stream = new Stream.fromIterable([1, 2, 3, 4, 5]); |
| queue = new StreamQueue(new Stream.fromIterable([1, 2, 3, 4, 5])); |
| errorStream = |
| new Stream.fromFuture(new Future.error("oh no!", StackTrace.current)); |
| errorQueue = new StreamQueue( |
| new Stream.fromFuture(new Future.error("oh no!", StackTrace.current))); |
| }); |
| |
| group("emits()", () { |
| test("matches the first event of a Stream", () { |
| expect(stream, emits(1)); |
| }); |
| |
| test("rejects the first event of a Stream", () { |
| expect( |
| expectLater(stream, emits(2)), |
| throwsTestFailure(allOf([ |
| startsWith("Expected: should emit an event that <2>\n"), |
| endsWith(" Which: emitted * 1\n" |
| " * 2\n" |
| " * 3\n" |
| " * 4\n" |
| " * 5\n" |
| " x Stream closed.\n") |
| ]))); |
| }); |
| |
| test("matches and consumes the next event of a StreamQueue", () { |
| expect(queue, emits(1)); |
| expect(queue.next, completion(equals(2))); |
| expect(queue, emits(3)); |
| expect(queue.next, completion(equals(4))); |
| }); |
| |
| test("rejects and does not consume the first event of a StreamQueue", () { |
| expect( |
| expectLater(queue, emits(2)), |
| throwsTestFailure(allOf([ |
| startsWith("Expected: should emit an event that <2>\n"), |
| endsWith(" Which: emitted * 1\n" |
| " * 2\n" |
| " * 3\n" |
| " * 4\n" |
| " * 5\n" |
| " x Stream closed.\n") |
| ]))); |
| |
| expect(queue, emits(1)); |
| }); |
| |
| test("rejects an empty stream", () { |
| expect( |
| expectLater(new Stream.empty(), emits(1)), |
| throwsTestFailure(allOf([ |
| startsWith("Expected: should emit an event that <1>\n"), |
| endsWith(" Which: emitted x Stream closed.\n") |
| ]))); |
| }); |
| |
| test("forwards a stream error", () { |
| expect(expectLater(errorStream, emits(1)), throwsA("oh no!")); |
| }); |
| |
| test("wraps a normal matcher", () { |
| expect(queue, emits(lessThan(5))); |
| expect(expectLater(queue, emits(greaterThan(5))), |
| throwsTestFailure(anything)); |
| }); |
| |
| test("returns a StreamMatcher as-is", () { |
| expect(queue, emits(emitsThrough(4))); |
| expect(queue, emits(5)); |
| }); |
| }); |
| |
| group("emitsDone", () { |
| test("succeeds for an empty stream", () { |
| expect(new Stream.empty(), emitsDone); |
| }); |
| |
| test("fails for a stream with events", () { |
| expect( |
| expectLater(stream, emitsDone), |
| throwsTestFailure(allOf([ |
| startsWith("Expected: should be done\n"), |
| endsWith(" Which: emitted * 1\n" |
| " * 2\n" |
| " * 3\n" |
| " * 4\n" |
| " * 5\n" |
| " x Stream closed.\n") |
| ]))); |
| }); |
| }); |
| |
| group("emitsError()", () { |
| test("consumes a matching error", () { |
| expect(errorQueue, emitsError("oh no!")); |
| expect(errorQueue.hasNext, completion(isFalse)); |
| }); |
| |
| test("fails for a non-matching error", () { |
| expect( |
| expectLater(errorStream, emitsError("oh heck")), |
| throwsTestFailure(allOf([ |
| startsWith("Expected: should emit an error that 'oh heck'\n"), |
| contains(" Which: emitted ! oh no!\n"), |
| contains(" x Stream closed.\n" |
| " which threw 'oh no!'\n" |
| " stack "), |
| endsWith(" which is different.\n" |
| " Expected: oh heck\n" |
| " Actual: oh no!\n" |
| " ^\n" |
| " Differ at offset 3\n") |
| ]))); |
| }); |
| |
| test("fails for a stream with events", () { |
| expect( |
| expectLater(stream, emitsDone), |
| throwsTestFailure(allOf([ |
| startsWith("Expected: should be done\n"), |
| endsWith(" Which: emitted * 1\n" |
| " * 2\n" |
| " * 3\n" |
| " * 4\n" |
| " * 5\n" |
| " x Stream closed.\n") |
| ]))); |
| }); |
| }); |
| |
| group("mayEmit()", () { |
| test("consumes a matching event", () { |
| expect(queue, mayEmit(1)); |
| expect(queue, emits(2)); |
| }); |
| |
| test("allows a non-matching event", () { |
| expect(queue, mayEmit("fish")); |
| expect(queue, emits(1)); |
| }); |
| }); |
| |
| group("emitsAnyOf()", () { |
| test("consumes an event that matches a matcher", () { |
| expect(queue, emitsAnyOf([2, 1, 3])); |
| expect(queue, emits(2)); |
| }); |
| |
| test("consumes as many events as possible", () { |
| expect( |
| queue, |
| emitsAnyOf([ |
| 1, |
| emitsInOrder([1, 2]), |
| emitsInOrder([1, 2, 3]) |
| ])); |
| |
| expect(queue, emits(4)); |
| }); |
| |
| test("fails if no matchers match", () { |
| expect( |
| expectLater(stream, emitsAnyOf([2, 3, 4])), |
| throwsTestFailure(allOf([ |
| startsWith("Expected: should do one of the following:\n" |
| " * emit an event that <2>\n" |
| " * emit an event that <3>\n" |
| " * emit an event that <4>\n"), |
| endsWith(" Which: emitted * 1\n" |
| " * 2\n" |
| " * 3\n" |
| " * 4\n" |
| " * 5\n" |
| " x Stream closed.\n" |
| " which failed all options:\n" |
| " * failed to emit an event that <2>\n" |
| " * failed to emit an event that <3>\n" |
| " * failed to emit an event that <4>\n") |
| ]))); |
| }); |
| |
| test("allows an error if any matcher matches", () { |
| expect(errorStream, emitsAnyOf([1, 2, emitsError("oh no!")])); |
| }); |
| |
| test("rethrows an error if no matcher matches", () { |
| expect( |
| expectLater(errorStream, emitsAnyOf([1, 2, 3])), throwsA("oh no!")); |
| }); |
| }); |
| |
| group("emitsInOrder()", () { |
| test("consumes matching events", () { |
| expect(queue, emitsInOrder([1, 2, emitsThrough(4)])); |
| expect(queue, emits(5)); |
| }); |
| |
| test("fails if the matchers don't match in order", () { |
| expect( |
| expectLater(queue, emitsInOrder([1, 3, 2])), |
| throwsTestFailure(allOf([ |
| startsWith("Expected: should do the following in order:\n" |
| " * emit an event that <1>\n" |
| " * emit an event that <3>\n" |
| " * emit an event that <2>\n"), |
| endsWith(" Which: emitted * 1\n" |
| " * 2\n" |
| " * 3\n" |
| " * 4\n" |
| " * 5\n" |
| " x Stream closed.\n" |
| " which didn't emit an event that <3>\n") |
| ]))); |
| }); |
| }); |
| |
| group("emitsThrough()", () { |
| test("consumes events including those matching the matcher", () { |
| expect(queue, emitsThrough(emitsInOrder([3, 4]))); |
| expect(queue, emits(5)); |
| }); |
| |
| test("consumes the entire queue with emitsDone", () { |
| expect(queue, emitsThrough(emitsDone)); |
| expect(queue.hasNext, completion(isFalse)); |
| }); |
| |
| test("fails if the queue never matches the matcher", () { |
| expect( |
| expectLater(queue, emitsThrough(6)), |
| throwsTestFailure(allOf([ |
| startsWith("Expected: should eventually emit an event that <6>\n"), |
| endsWith(" Which: emitted * 1\n" |
| " * 2\n" |
| " * 3\n" |
| " * 4\n" |
| " * 5\n" |
| " x Stream closed.\n" |
| " which never did emit an event that <6>\n") |
| ]))); |
| }); |
| }); |
| |
| group("mayEmitMultiple()", () { |
| test("consumes multiple instances of the given matcher", () { |
| expect(queue, mayEmitMultiple(lessThan(3))); |
| expect(queue, emits(3)); |
| }); |
| |
| test("consumes zero instances of the given matcher", () { |
| expect(queue, mayEmitMultiple(6)); |
| expect(queue, emits(1)); |
| }); |
| |
| test("doesn't rethrow errors", () { |
| expect(errorQueue, mayEmitMultiple(1)); |
| expect(errorQueue, emitsError("oh no!")); |
| }); |
| }); |
| |
| group("neverEmits()", () { |
| test("succeeds if the event never matches", () { |
| expect(queue, neverEmits(6)); |
| expect(queue, emits(1)); |
| }); |
| |
| test("fails if the event matches", () { |
| expect( |
| expectLater(stream, neverEmits(4)), |
| throwsTestFailure(allOf([ |
| startsWith("Expected: should never emit an event that <4>\n"), |
| endsWith(" Which: emitted * 1\n" |
| " * 2\n" |
| " * 3\n" |
| " * 4\n" |
| " * 5\n" |
| " x Stream closed.\n" |
| " which after 3 events did emit an event that <4>\n") |
| ]))); |
| }); |
| |
| test("fails if emitsDone matches", () { |
| expect(expectLater(stream, neverEmits(emitsDone)), |
| throwsTestFailure(anything)); |
| }); |
| |
| test("doesn't rethrow errors", () { |
| expect(errorQueue, neverEmits(6)); |
| expect(errorQueue, emitsError("oh no!")); |
| }); |
| }); |
| |
| group("emitsInAnyOrder()", () { |
| test("consumes events that match in any order", () { |
| expect(queue, emitsInAnyOrder([3, 1, 2])); |
| expect(queue, emits(4)); |
| }); |
| |
| test("fails if the events don't match in any order", () { |
| expect( |
| expectLater(stream, emitsInAnyOrder([4, 1, 2])), |
| throwsTestFailure(allOf([ |
| startsWith("Expected: should do the following in any order:\n" |
| " * emit an event that <4>\n" |
| " * emit an event that <1>\n" |
| " * emit an event that <2>\n"), |
| endsWith(" Which: emitted * 1\n" |
| " * 2\n" |
| " * 3\n" |
| " * 4\n" |
| " * 5\n" |
| " x Stream closed.\n") |
| ]))); |
| }); |
| |
| test("doesn't rethrow if some ordering matches", () { |
| expect(errorQueue, emitsInAnyOrder([emitsDone, emitsError("oh no!")])); |
| }); |
| |
| test("rethrows if no ordering matches", () { |
| expect( |
| expectLater(errorQueue, emitsInAnyOrder([1, emitsError("oh no!")])), |
| throwsA("oh no!")); |
| }); |
| }); |
| } |