Chromium Code Reviews| Index: pkg/matcher/lib/src/prints_matcher.dart |
| diff --git a/pkg/matcher/lib/src/prints_matcher.dart b/pkg/matcher/lib/src/prints_matcher.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..e3e3ccce7cca8be1d27a8a0a879d64e8dd8cd4ee |
| --- /dev/null |
| +++ b/pkg/matcher/lib/src/prints_matcher.dart |
| @@ -0,0 +1,73 @@ |
| +// Copyright (c) 2014, 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. |
| + |
| +library matcher.prints_matcher; |
| + |
| +import 'dart:async'; |
| + |
| +import 'description.dart'; |
| +import 'expect.dart'; |
| +import 'interfaces.dart'; |
| +import 'future_matchers.dart'; |
| +import 'util.dart'; |
| + |
| +/// Matches a [Function] that prints text that matches [matcher]. |
| +/// |
| +/// [matcher] may be a String or a [Matcher]. |
| +/// |
| +/// If the function this runs against returns a [Future], all text printed by |
| +/// the function (using [Zone] scoping) until that Future completes will be |
|
Bob Nystrom
2014/12/05 18:14:53
"will be" -> "is".
nweiz
2014/12/09 01:01:01
Done.
|
| +/// matched. |
| +/// |
| +/// This only tracks text printed using the [print] function. |
|
Bob Nystrom
2014/12/05 18:14:53
This means going between print(), stdout.write(),
nweiz
2014/12/09 01:01:01
That's already true; anyone could be using a custo
|
| +Matcher prints(matcher) => new _Prints(wrapMatcher(matcher)); |
| + |
| +class _Prints extends Matcher { |
| + final Matcher _matcher; |
| + |
| + _Prints(this._matcher); |
| + |
| + bool matches(item, Map matchState) { |
| + if (item is! Function) return false; |
| + |
| + var buffer = new StringBuffer(); |
| + var result = runZoned(item, zoneSpecification: |
| + new ZoneSpecification(print: (_, __, ____, line) { |
| + buffer.writeln(line); |
| + })); |
| + |
| + if (result is! Future) { |
| + var actual = buffer.toString(); |
| + matchState['prints.actual'] = actual; |
| + return _matcher.matches(actual, matchState); |
| + } |
| + |
| + return completes.matches(result.then(wrapAsync((_) { |
| + expect(buffer.toString(), _matcher); |
| + }, 'prints')), matchState); |
| + } |
| + |
| + Description describe(Description description) => |
| + description.add('prints ').addDescriptionOf(_matcher); |
| + |
| + Description describeMismatch(item, Description description, Map matchState, |
| + bool verbose) { |
| + var actual = matchState.remove('prints.actual'); |
| + if (actual == null) return description; |
| + if (actual.isEmpty) return description.add("printed nothing."); |
| + |
| + description.add('printed ').addDescriptionOf(actual); |
| + |
| + // Create a new description for the matcher because at least |
| + // [_StringEqualsMatcher] replaces the previous contents of the description. |
| + var innerMismatch = _matcher.describeMismatch( |
| + actual, new StringDescription(), matchState, verbose).toString(); |
| + |
| + if (innerMismatch.isNotEmpty) { |
| + description.add('\n Which: ').add(innerMismatch.toString()); |
| + } |
| + |
| + return description; |
| + } |
| +} |