Index: packages/matcher/lib/src/iterable_matchers.dart |
diff --git a/packages/matcher/lib/src/iterable_matchers.dart b/packages/matcher/lib/src/iterable_matchers.dart |
index 7185e921003592775e6f19ace27fdd3e8e06e814..91591042b8a6b0dc8d7e3824d63a141609aa2344 100644 |
--- a/packages/matcher/lib/src/iterable_matchers.dart |
+++ b/packages/matcher/lib/src/iterable_matchers.dart |
@@ -2,8 +2,6 @@ |
// 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.iterable_matchers; |
- |
import 'core_matchers.dart'; |
import 'description.dart'; |
import 'interfaces.dart'; |
@@ -57,8 +55,8 @@ class _EveryElement extends _IterableMatcher { |
mismatchDescription.add(' at index $index'); |
return mismatchDescription; |
} |
- return super.describeMismatch( |
- item, mismatchDescription, matchState, verbose); |
+ return super |
+ .describeMismatch(item, mismatchDescription, matchState, verbose); |
} |
} |
@@ -138,8 +136,8 @@ abstract class _IterableMatcher extends Matcher { |
if (item is! Iterable) { |
return mismatchDescription.addDescriptionOf(item).add(' not an Iterable'); |
} else { |
- return super.describeMismatch( |
- item, mismatchDescription, matchState, verbose); |
+ return super |
+ .describeMismatch(item, mismatchDescription, matchState, verbose); |
} |
} |
} |
@@ -202,8 +200,8 @@ class _UnorderedMatches extends Matcher { |
.addAll('[', ', ', ']', _expected) |
.add(' unordered'); |
- Description describeMismatch( |
- item, Description mismatchDescription, Map matchState, bool verbose) => |
+ Description describeMismatch(item, Description mismatchDescription, |
+ Map matchState, bool verbose) => |
mismatchDescription.add(_test(item)); |
} |
@@ -213,8 +211,8 @@ class _UnorderedMatches extends Matcher { |
/// returning whether they match, will be applied to each pair in order. |
/// [description] should be a meaningful name for the comparator. |
Matcher pairwiseCompare( |
- Iterable expected, bool comparator(a, b), String description) => |
- new _PairwiseCompare(expected, comparator, description); |
+ Iterable expected, bool comparator(a, b), String description) => |
+ new _PairwiseCompare(expected, comparator, description); |
typedef bool _Comparator(a, b); |
@@ -233,11 +231,8 @@ class _PairwiseCompare extends _IterableMatcher { |
for (var e in _expected) { |
iterator.moveNext(); |
if (!_comparator(e, iterator.current)) { |
- addStateInfo(matchState, { |
- 'index': i, |
- 'expected': e, |
- 'actual': iterator.current |
- }); |
+ addStateInfo(matchState, |
+ {'index': i, 'expected': e, 'actual': iterator.current}); |
return false; |
} |
i++; |
@@ -265,3 +260,47 @@ class _PairwiseCompare extends _IterableMatcher { |
} |
} |
} |
+ |
+/// Matches [Iterable]s which contain an element matching every value in |
+/// [expected] in the same order, but may contain additional values interleaved |
+/// throughout. |
+/// |
+/// For example: `[0, 1, 0, 2, 0]` matches `containsAllInOrder([1, 2])` but not |
+/// `containsAllInOrder([2, 1])` or `containsAllInOrder([1, 2, 3])`. |
+Matcher containsAllInOrder(Iterable expected) => |
+ new _ContainsAllInOrder(expected); |
+ |
+class _ContainsAllInOrder implements Matcher { |
+ final Iterable _expected; |
+ |
+ _ContainsAllInOrder(this._expected); |
+ |
+ String _test(item, Map matchState) { |
+ if (item is! Iterable) return 'not an iterable'; |
+ var matchers = _expected.map(wrapMatcher).toList(); |
+ var matcherIndex = 0; |
+ for (var value in item) { |
+ if (matchers[matcherIndex].matches(value, matchState)) matcherIndex++; |
+ if (matcherIndex == matchers.length) return null; |
+ } |
+ return new StringDescription() |
+ .add('did not find a value matching ') |
+ .addDescriptionOf(matchers[matcherIndex]) |
+ .add(' following expected prior values') |
+ .toString(); |
+ } |
+ |
+ @override |
+ bool matches(item, Map matchState) => _test(item, matchState) == null; |
+ |
+ @override |
+ Description describe(Description description) => description |
+ .add('contains in order(') |
+ .addDescriptionOf(_expected) |
+ .add(')'); |
+ |
+ @override |
+ Description describeMismatch(item, Description mismatchDescription, |
+ Map matchState, bool verbose) => |
+ mismatchDescription.add(_test(item, matchState)); |
+} |