Line data Source code
1 : // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2 : // for details. All rights reserved. Use of this source code is governed by a
3 : // BSD-style license that can be found in the LICENSE file.
4 :
5 : import 'dart:async';
6 :
7 : import 'package:matcher/matcher.dart';
8 :
9 : import '../backend/invoker.dart';
10 : import 'expect.dart';
11 :
12 : /// A matcher that does asynchronous computation.
13 : ///
14 : /// Rather than implementing [matches], subclasses implement [matchAsync].
15 : /// [AsyncMatcher.matches] ensures that the test doesn't complete until the
16 : /// returned future completes, and [expect] returns a future that completes when
17 : /// the returned future completes so that tests can wait for it.
18 : abstract class AsyncMatcher extends Matcher {
19 1 : const AsyncMatcher();
20 :
21 : /// Returns `null` if this matches [item], or a [String] description of the
22 : /// failure if it doesn't match.
23 : ///
24 : /// This can return a [Future] or a synchronous value. If it returns a
25 : /// [Future], neither [expect] nor the test will complete until that [Future]
26 : /// completes.
27 : ///
28 : /// If this returns a [String] synchronously, [expect] will synchronously
29 : /// throw a [TestFailure] and [matches] will synchronusly return `false`.
30 : /*FutureOr<String>*/ matchAsync(item);
31 :
32 : bool matches(item, Map matchState) {
33 0 : var result = matchAsync(item);
34 0 : expect(
35 : result,
36 0 : anyOf([
37 0 : equals(null),
38 0 : new isInstanceOf<Future>(),
39 0 : new isInstanceOf<String>()
40 : ]),
41 : reason: "matchAsync() may only return a String, a Future, or null.");
42 :
43 0 : if (result is Future) {
44 0 : Invoker.current.addOutstandingCallback();
45 0 : result.then((realResult) {
46 0 : if (realResult != null) fail(formatFailure(this, item, realResult));
47 0 : Invoker.current.removeOutstandingCallback();
48 : });
49 0 : } else if (result is String) {
50 0 : matchState[this] = result;
51 : return false;
52 : }
53 :
54 : return true;
55 : }
56 :
57 : Description describeMismatch(
58 : item, Description description, Map matchState, bool verbose) =>
59 0 : new StringDescription(matchState[this]);
60 : }
|