Line data Source code
1 : // Copyright (c) 2014, 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 'async_matcher.dart'; 10 : import 'expect.dart'; 11 : import 'util/pretty_print.dart'; 12 : 13 : /// Matches a [Function] that prints text that matches [matcher]. 14 : /// 15 : /// [matcher] may be a String or a [Matcher]. 16 : /// 17 : /// If the function this runs against returns a [Future], all text printed by 18 : /// the function (using [Zone] scoping) until that Future completes is matched. 19 : /// 20 : /// This only tracks text printed using the [print] function. 21 : /// 22 : /// This returns an [AsyncMatcher], so [expect] won't complete until the matched 23 : /// function does. 24 0 : Matcher prints(matcher) => _Prints(wrapMatcher(matcher)); 25 : 26 : class _Prints extends AsyncMatcher { 27 : final Matcher _matcher; 28 : 29 0 : _Prints(this._matcher); 30 : 31 : // Avoid async/await so we synchronously fail if the function is 32 : // synchronous. 33 0 : @override 34 : dynamic /*FutureOr<String>*/ matchAsync(item) { 35 0 : if (item is! Function()) return 'was not a unary Function'; 36 : 37 0 : var buffer = StringBuffer(); 38 0 : var result = runZoned(item, 39 0 : zoneSpecification: ZoneSpecification(print: (_, __, ____, line) { 40 0 : buffer.writeln(line); 41 : })); 42 : 43 0 : return result is Future 44 0 : ? result.then((_) => _check(buffer.toString())) 45 0 : : _check(buffer.toString()); 46 : } 47 : 48 0 : @override 49 : Description describe(Description description) => 50 0 : description.add('prints ').addDescriptionOf(_matcher); 51 : 52 : /// Verifies that [actual] matches [_matcher] and returns a [String] 53 : /// description of the failure if it doesn't. 54 0 : String? _check(String actual) { 55 0 : var matchState = {}; 56 0 : if (_matcher.matches(actual, matchState)) return null; 57 : 58 0 : var result = _matcher 59 0 : .describeMismatch(actual, StringDescription(), matchState, false) 60 0 : .toString(); 61 : 62 0 : var buffer = StringBuffer(); 63 0 : if (actual.isEmpty) { 64 0 : buffer.writeln('printed nothing'); 65 : } else { 66 0 : buffer.writeln(indent(prettyPrint(actual), first: 'printed ')); 67 : } 68 0 : if (result.isNotEmpty) buffer.writeln(indent(result, first: ' which ')); 69 0 : return buffer.toString().trimRight(); 70 : } 71 : }