LCOV - code coverage report
Current view: top level - test_api-0.4.8/lib/src/expect - expect.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 18 47 38.3 %
Date: 2021-11-28 14:37:50 Functions: 0 0 -

          Line data    Source code
       1             : // Copyright (c) 2015, 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 'package:matcher/matcher.dart';
       6             : import 'package:test_api/hooks.dart';
       7             : 
       8             : import 'async_matcher.dart';
       9             : import 'util/pretty_print.dart';
      10             : 
      11             : /// The type used for functions that can be used to build up error reports
      12             : /// upon failures in [expect].
      13             : @Deprecated('Will be removed in 0.13.0.')
      14             : typedef ErrorFormatter = String Function(dynamic actual, Matcher matcher,
      15             :     String? reason, Map matchState, bool verbose);
      16             : 
      17             : /// Assert that [actual] matches [matcher].
      18             : ///
      19             : /// This is the main assertion function. [reason] is optional and is typically
      20             : /// not supplied, as a reason is generated from [matcher]; if [reason]
      21             : /// is included it is appended to the reason generated by the matcher.
      22             : ///
      23             : /// [matcher] can be a value in which case it will be wrapped in an
      24             : /// [equals] matcher.
      25             : ///
      26             : /// If the assertion fails a [TestFailure] is thrown.
      27             : ///
      28             : /// If [skip] is a String or `true`, the assertion is skipped. The arguments are
      29             : /// still evaluated, but [actual] is not verified to match [matcher]. If
      30             : /// [actual] is a [Future], the test won't complete until the future emits a
      31             : /// value.
      32             : ///
      33             : /// If [skip] is a string, it should explain why the assertion is skipped; this
      34             : /// reason will be printed when running the test.
      35             : ///
      36             : /// Certain matchers, like [completion] and [throwsA], either match or fail
      37             : /// asynchronously. When you use [expect] with these matchers, it ensures that
      38             : /// the test doesn't complete until the matcher has either matched or failed. If
      39             : /// you want to wait for the matcher to complete before continuing the test, you
      40             : /// can call [expectLater] instead and `await` the result.
      41          11 : void expect(actual, matcher,
      42             :     {String? reason,
      43             :     skip,
      44             :     @Deprecated('Will be removed in 0.13.0.') bool verbose = false,
      45             :     @Deprecated('Will be removed in 0.13.0.') ErrorFormatter? formatter}) {
      46          11 :   _expect(actual, matcher,
      47             :       reason: reason, skip: skip, verbose: verbose, formatter: formatter);
      48             : }
      49             : 
      50             : /// Just like [expect], but returns a [Future] that completes when the matcher
      51             : /// has finished matching.
      52             : ///
      53             : /// For the [completes] and [completion] matchers, as well as [throwsA] and
      54             : /// related matchers when they're matched against a [Future], the returned
      55             : /// future completes when the matched future completes. For the [prints]
      56             : /// matcher, it completes when the future returned by the callback completes.
      57             : /// Otherwise, it completes immediately.
      58             : ///
      59             : /// If the matcher fails asynchronously, that failure is piped to the returned
      60             : /// future where it can be handled by user code.
      61           0 : Future expectLater(actual, matcher, {String? reason, skip}) =>
      62           0 :     _expect(actual, matcher, reason: reason, skip: skip);
      63             : 
      64             : /// The implementation of [expect] and [expectLater].
      65             : ///
      66             : // TODO: why is this necessary? Is @alwaysThrows not working in NNBD?
      67             : // ignore: body_might_complete_normally
      68          11 : Future _expect(actual, matcher,
      69             :     {String? reason, skip, bool verbose = false, ErrorFormatter? formatter}) {
      70          11 :   final test = TestHandle.current;
      71           0 :   formatter ??= (actual, matcher, reason, matchState, verbose) {
      72           0 :     var mismatchDescription = StringDescription();
      73           0 :     matcher.describeMismatch(actual, mismatchDescription, matchState, verbose);
      74             : 
      75           0 :     return formatFailure(matcher, actual, mismatchDescription.toString(),
      76             :         reason: reason);
      77             :   };
      78             : 
      79           0 :   if (skip != null && skip is! bool && skip is! String) {
      80           0 :     throw ArgumentError.value(skip, 'skip', 'must be a bool or a String');
      81             :   }
      82             : 
      83          11 :   matcher = wrapMatcher(matcher);
      84           0 :   if (skip != null && skip != false) {
      85             :     String message;
      86           0 :     if (skip is String) {
      87           0 :       message = 'Skip expect: $skip';
      88             :     } else if (reason != null) {
      89           0 :       message = 'Skip expect ($reason).';
      90             :     } else {
      91           0 :       var description = StringDescription().addDescriptionOf(matcher);
      92           0 :       message = 'Skip expect ($description).';
      93             :     }
      94             : 
      95           0 :     test.markSkipped(message);
      96           0 :     return Future.sync(() {});
      97             :   }
      98             : 
      99          11 :   if (matcher is AsyncMatcher) {
     100             :     // Avoid async/await so that expect() throws synchronously when possible.
     101           5 :     var result = matcher.matchAsync(actual);
     102           5 :     expect(result,
     103          25 :         anyOf([equals(null), TypeMatcher<Future>(), TypeMatcher<String>()]),
     104             :         reason: 'matchAsync() may only return a String, a Future, or null.');
     105             : 
     106           5 :     if (result is String) {
     107           0 :       fail(formatFailure(matcher, actual, result, reason: reason));
     108           5 :     } else if (result is Future) {
     109           5 :       final outstandingWork = test.markPending();
     110          10 :       return result.then((realResult) {
     111             :         if (realResult == null) return;
     112           0 :         fail(formatFailure(matcher as Matcher, actual, realResult as String,
     113             :             reason: reason));
     114          10 :       }).whenComplete(() {
     115             :         // Always remove this, in case the failure is caught and handled
     116             :         // gracefully.
     117           5 :         outstandingWork.complete();
     118             :       });
     119             :     }
     120             : 
     121           0 :     return Future.sync(() {});
     122             :   }
     123             : 
     124          11 :   var matchState = {};
     125             :   try {
     126          11 :     if ((matcher as Matcher).matches(actual, matchState)) {
     127          22 :       return Future.sync(() {});
     128             :     }
     129             :   } catch (e, trace) {
     130           0 :     reason ??= '$e at $trace';
     131             :   }
     132           0 :   fail(formatter(actual, matcher as Matcher, reason, matchState, verbose));
     133             : }
     134             : 
     135             : /// Convenience method for throwing a new [TestFailure] with the provided
     136             : /// [message].
     137           0 : Never fail(String message) => throw TestFailure(message);
     138             : 
     139             : // The default error formatter.
     140           0 : @Deprecated('Will be removed in 0.13.0.')
     141             : String formatFailure(Matcher expected, actual, String which, {String? reason}) {
     142           0 :   var buffer = StringBuffer();
     143           0 :   buffer.writeln(indent(prettyPrint(expected), first: 'Expected: '));
     144           0 :   buffer.writeln(indent(prettyPrint(actual), first: '  Actual: '));
     145           0 :   if (which.isNotEmpty) buffer.writeln(indent(which, first: '   Which: '));
     146           0 :   if (reason != null) buffer.writeln(reason);
     147           0 :   return buffer.toString();
     148             : }

Generated by: LCOV version 1.14